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
@@ -1,54 +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
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
@@ -1,188 +1,188 @@
1
- require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
2
- require 'pathname'
3
- require 'fileutils'
4
- require 'digest/md5'
5
- require 'thread'
6
- require 'chef/http/simple'
7
-
8
- class Chef
9
- module Provisioning
10
- class ConvergenceStrategy
11
- class InstallCached < PrecreateChefObjects
12
- # convergence_options is a hash of setup convergence_options, including:
13
- # - :chef_server
14
- # - :allow_overwrite_keys
15
- # - :source_key, :source_key_path, :source_key_pass_phrase
16
- # - :private_key_options
17
- # - :ohai_hints
18
- # - :public_key_path, :public_key_format
19
- # - :admin, :validator
20
- # - :chef_client_timeout
21
- # - :client_rb_path, :client_pem_path
22
- # - :chef_version, :prerelease, :package_cache_path
23
- # - :package_metadata
24
- def initialize(convergence_options, config)
25
- convergence_options = Cheffish::MergedConfig.new(convergence_options, {
26
- :client_rb_path => '/etc/chef/client.rb',
27
- :client_pem_path => '/etc/chef/client.pem'
28
- })
29
- super(convergence_options, config)
30
- @client_rb_path ||= convergence_options[:client_rb_path]
31
- @chef_version ||= convergence_options[:chef_version]
32
- @prerelease ||= convergence_options[:prerelease]
33
- @package_cache_path ||= convergence_options[:package_cache_path] || "#{ENV['HOME']}/.chef/package_cache"
34
- @package_cache = {}
35
- @tmp_dir = '/tmp'
36
- @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
37
- FileUtils.mkdir_p(@package_cache_path)
38
- @package_cache_lock = Mutex.new
39
- @package_metadata ||= convergence_options[:package_metadata]
40
- end
41
-
42
- attr_reader :client_rb_path
43
- attr_reader :client_pem_path
44
- attr_reader :chef_version
45
- attr_reader :prerelease
46
-
47
- def setup_convergence(action_handler, machine)
48
- super
49
-
50
- # Check for existing chef client.
51
- version = machine.execute_always('chef-client -v')
52
-
53
- # Don't do install/upgrade if a chef client exists and
54
- # no chef version is defined by user configs or
55
- # the chef client's version already matches user config
56
- if version.exitstatus == 0
57
- version = version.stdout.strip
58
- if !chef_version
59
- return
60
- elsif version =~ /Chef: #{chef_version}$/
61
- Chef::Log.debug "Already installed chef version #{version}"
62
- return
63
- elsif version.include?(chef_version)
64
- Chef::Log.warn "Installed chef version #{version} contains desired version #{chef_version}. " +
65
- "If you see this message on consecutive chef runs tighten your desired version constraint to prevent " +
66
- "multiple convergence."
67
- end
68
- end
69
-
70
- # Install chef client
71
- platform, platform_version, machine_architecture = machine.detect_os(action_handler)
72
- package_file = download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
73
- remote_package_file = "#{@tmp_dir}/#{File.basename(package_file)}"
74
- machine.upload_file(action_handler, package_file, remote_package_file)
75
- install_package(action_handler, machine, platform, remote_package_file)
76
- end
77
-
78
- def converge(action_handler, machine)
79
- super
80
-
81
- action_handler.open_stream(machine.node['name']) do |stdout|
82
- action_handler.open_stream(machine.node['name']) do |stderr|
83
- command_line = "chef-client"
84
- command_line << " -c #{@client_rb_path} -l #{config[:log_level].to_s}" if config[:log_level]
85
- machine.execute(action_handler, command_line,
86
- :stream_stdout => stdout,
87
- :stream_stderr => stderr,
88
- :timeout => @chef_client_timeout)
89
- end
90
- end
91
- end
92
-
93
- private
94
-
95
- def download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
96
- @package_cache_lock.synchronize do
97
- @package_cache ||= {}
98
- @package_cache[platform] ||= {}
99
- @package_cache[platform][platform_version] ||= {}
100
- @package_cache[platform][platform_version][machine_architecture] ||= { :lock => Mutex.new }
101
- end
102
- @package_cache[platform][platform_version][machine_architecture][:lock].synchronize do
103
- if !@package_cache[platform][platform_version][machine_architecture][:file]
104
- #
105
- # Grab metadata
106
- #
107
- metadata = @package_metadata
108
- if !metadata
109
- Chef::Log.info("No metadata supplied, downloading it...")
110
- metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
111
- end
112
-
113
- # Download actual package desired by metadata
114
- package_file = "#{@package_cache_path}/#{URI(metadata[:url]).path.split('/')[-1]}"
115
-
116
- Chef::Log.debug("Package metadata: #{metadata}")
117
- Chef::Provisioning.inline_resource(action_handler) do
118
- remote_file package_file do
119
- source metadata[:url]
120
- checksum metadata[:sha256]
121
- end
122
- end
123
-
124
- @package_cache[platform][platform_version][machine_architecture][:file] = package_file
125
- end
126
- end
127
- @package_cache[platform][platform_version][machine_architecture][:file]
128
- end
129
-
130
- def download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
131
- #
132
- # Figure out the URL to the metadata
133
- #
134
- metadata_url="https://www.chef.io/chef/metadata"
135
- metadata_url << "?v=#{@chef_version}"
136
- metadata_url << "&prerelease=#{@prerelease ? 'true' : 'false'}"
137
- metadata_url << "&p=#{platform.strip}"
138
- metadata_url << "&pv=#{platform_version.strip}"
139
- metadata_url << "&m=#{machine_architecture.strip}"
140
- use_ssl = true
141
-
142
- # solaris 9 lacks openssl, solaris 10 lacks recent enough credentials - your base O/S is completely insecure, please upgrade
143
- if platform == 'solaris2' && (platform_version == '5.9' || platform_version == '5.10')
144
- metadata_url.sub(/^https/, 'http')
145
- use_ssl = false
146
- end
147
-
148
- # Download and parse the metadata
149
- Chef::Log.debug("Getting metadata for machine #{machine.node['name']}: #{metadata_url}")
150
- uri = URI(metadata_url)
151
- metadata_str = Chef::HTTP::Simple.new(uri).get(uri)
152
- metadata = {}
153
- metadata_str.each_line do |line|
154
- key, value = line.split("\t", 2)
155
- metadata[key.to_sym] = value.chomp
156
- end
157
- metadata
158
- end
159
-
160
- def install_package(action_handler, machine, platform, remote_package_file)
161
- extension = File.extname(remote_package_file)
162
- result = case extension
163
- when '.rpm'
164
- if platform == "wrlinux"
165
- machine.execute(action_handler, "yum install -yv \"#{remote_package_file}\"")
166
- else
167
- machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
168
- end
169
- when '.deb'
170
- machine.execute(action_handler, "dpkg -i \"#{remote_package_file}\"")
171
- when '.solaris'
172
- machine.write_file(action_handler, "#{@tmp_dir}/nocheck", <<EOM)
173
- conflict=nocheck
174
- action=nocheck
175
- mail=
176
- EOM
177
- machine.execute(action_handler, "pkgrm -a \"#{@tmp_dir}/nocheck\" -n chef")
178
- machine.execute(action_handler, "pkgadd -n -d \"#{remote_package_file}\" -a \"#{@tmp_dir}/nocheck\" chef")
179
- when '.sh'
180
- machine.execute(action_handler, "sh \"#{remote_package_file}\"")
181
- else
182
- raise "Unknown package extension '#{extension}' for file #{remote_package_file}"
183
- end
184
- end
185
- end
186
- end
187
- end
188
- end
1
+ require 'chef/provisioning/convergence_strategy/precreate_chef_objects'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ require 'digest/md5'
5
+ require 'thread'
6
+ require 'chef/http/simple'
7
+
8
+ class Chef
9
+ module Provisioning
10
+ class ConvergenceStrategy
11
+ class InstallCached < PrecreateChefObjects
12
+ # convergence_options is a hash of setup convergence_options, including:
13
+ # - :chef_server
14
+ # - :allow_overwrite_keys
15
+ # - :source_key, :source_key_path, :source_key_pass_phrase
16
+ # - :private_key_options
17
+ # - :ohai_hints
18
+ # - :public_key_path, :public_key_format
19
+ # - :admin, :validator
20
+ # - :chef_client_timeout
21
+ # - :client_rb_path, :client_pem_path
22
+ # - :chef_version, :prerelease, :package_cache_path
23
+ # - :package_metadata
24
+ def initialize(convergence_options, config)
25
+ convergence_options = Cheffish::MergedConfig.new(convergence_options, {
26
+ :client_rb_path => '/etc/chef/client.rb',
27
+ :client_pem_path => '/etc/chef/client.pem'
28
+ })
29
+ super(convergence_options, config)
30
+ @client_rb_path ||= convergence_options[:client_rb_path]
31
+ @chef_version ||= convergence_options[:chef_version]
32
+ @prerelease ||= convergence_options[:prerelease]
33
+ @package_cache_path ||= convergence_options[:package_cache_path] || "#{ENV['HOME']}/.chef/package_cache"
34
+ @package_cache = {}
35
+ @tmp_dir = '/tmp'
36
+ @chef_client_timeout = convergence_options.has_key?(:chef_client_timeout) ? convergence_options[:chef_client_timeout] : 120*60 # Default: 2 hours
37
+ FileUtils.mkdir_p(@package_cache_path)
38
+ @package_cache_lock = Mutex.new
39
+ @package_metadata ||= convergence_options[:package_metadata]
40
+ end
41
+
42
+ attr_reader :client_rb_path
43
+ attr_reader :client_pem_path
44
+ attr_reader :chef_version
45
+ attr_reader :prerelease
46
+
47
+ def setup_convergence(action_handler, machine)
48
+ super
49
+
50
+ # Check for existing chef client.
51
+ version = machine.execute_always('chef-client -v')
52
+
53
+ # Don't do install/upgrade if a chef client exists and
54
+ # no chef version is defined by user configs or
55
+ # the chef client's version already matches user config
56
+ if version.exitstatus == 0
57
+ version = version.stdout.strip
58
+ if !chef_version
59
+ return
60
+ elsif version =~ /Chef: #{chef_version}$/
61
+ Chef::Log.debug "Already installed chef version #{version}"
62
+ return
63
+ elsif version.include?(chef_version)
64
+ Chef::Log.warn "Installed chef version #{version} contains desired version #{chef_version}. " +
65
+ "If you see this message on consecutive chef runs tighten your desired version constraint to prevent " +
66
+ "multiple convergence."
67
+ end
68
+ end
69
+
70
+ # Install chef client
71
+ platform, platform_version, machine_architecture = machine.detect_os(action_handler)
72
+ package_file = download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
73
+ remote_package_file = "#{@tmp_dir}/#{File.basename(package_file)}"
74
+ machine.upload_file(action_handler, package_file, remote_package_file)
75
+ install_package(action_handler, machine, platform, remote_package_file)
76
+ end
77
+
78
+ def converge(action_handler, machine)
79
+ super
80
+
81
+ action_handler.open_stream(machine.node['name']) do |stdout|
82
+ action_handler.open_stream(machine.node['name']) do |stderr|
83
+ command_line = "chef-client"
84
+ command_line << " -c #{@client_rb_path} -l #{config[:log_level].to_s}" if config[:log_level]
85
+ machine.execute(action_handler, command_line,
86
+ :stream_stdout => stdout,
87
+ :stream_stderr => stderr,
88
+ :timeout => @chef_client_timeout)
89
+ end
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def download_package_for_platform(action_handler, machine, platform, platform_version, machine_architecture)
96
+ @package_cache_lock.synchronize do
97
+ @package_cache ||= {}
98
+ @package_cache[platform] ||= {}
99
+ @package_cache[platform][platform_version] ||= {}
100
+ @package_cache[platform][platform_version][machine_architecture] ||= { :lock => Mutex.new }
101
+ end
102
+ @package_cache[platform][platform_version][machine_architecture][:lock].synchronize do
103
+ if !@package_cache[platform][platform_version][machine_architecture][:file]
104
+ #
105
+ # Grab metadata
106
+ #
107
+ metadata = @package_metadata
108
+ if !metadata
109
+ Chef::Log.info("No metadata supplied, downloading it...")
110
+ metadata = download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
111
+ end
112
+
113
+ # Download actual package desired by metadata
114
+ package_file = "#{@package_cache_path}/#{URI(metadata[:url]).path.split('/')[-1]}"
115
+
116
+ Chef::Log.debug("Package metadata: #{metadata}")
117
+ Chef::Provisioning.inline_resource(action_handler) do
118
+ remote_file package_file do
119
+ source metadata[:url]
120
+ checksum metadata[:sha256]
121
+ end
122
+ end
123
+
124
+ @package_cache[platform][platform_version][machine_architecture][:file] = package_file
125
+ end
126
+ end
127
+ @package_cache[platform][platform_version][machine_architecture][:file]
128
+ end
129
+
130
+ def download_metadata_for_platform(machine, platform, platform_version, machine_architecture)
131
+ #
132
+ # Figure out the URL to the metadata
133
+ #
134
+ metadata_url="https://www.chef.io/chef/metadata"
135
+ metadata_url << "?v=#{@chef_version}"
136
+ metadata_url << "&prerelease=#{@prerelease ? 'true' : 'false'}"
137
+ metadata_url << "&p=#{platform.strip}"
138
+ metadata_url << "&pv=#{platform_version.strip}"
139
+ metadata_url << "&m=#{machine_architecture.strip}"
140
+ use_ssl = true
141
+
142
+ # solaris 9 lacks openssl, solaris 10 lacks recent enough credentials - your base O/S is completely insecure, please upgrade
143
+ if platform == 'solaris2' && (platform_version == '5.9' || platform_version == '5.10')
144
+ metadata_url.sub(/^https/, 'http')
145
+ use_ssl = false
146
+ end
147
+
148
+ # Download and parse the metadata
149
+ Chef::Log.debug("Getting metadata for machine #{machine.node['name']}: #{metadata_url}")
150
+ uri = URI(metadata_url)
151
+ metadata_str = Chef::HTTP::Simple.new(uri).get(uri)
152
+ metadata = {}
153
+ metadata_str.each_line do |line|
154
+ key, value = line.split("\t", 2)
155
+ metadata[key.to_sym] = value.chomp
156
+ end
157
+ metadata
158
+ end
159
+
160
+ def install_package(action_handler, machine, platform, remote_package_file)
161
+ extension = File.extname(remote_package_file)
162
+ result = case extension
163
+ when '.rpm'
164
+ if platform == "wrlinux"
165
+ machine.execute(action_handler, "yum install -yv \"#{remote_package_file}\"")
166
+ else
167
+ machine.execute(action_handler, "rpm -Uvh --oldpackage --replacepkgs \"#{remote_package_file}\"")
168
+ end
169
+ when '.deb'
170
+ machine.execute(action_handler, "dpkg -i \"#{remote_package_file}\"")
171
+ when '.solaris'
172
+ machine.write_file(action_handler, "#{@tmp_dir}/nocheck", <<EOM)
173
+ conflict=nocheck
174
+ action=nocheck
175
+ mail=
176
+ EOM
177
+ machine.execute(action_handler, "pkgrm -a \"#{@tmp_dir}/nocheck\" -n chef")
178
+ machine.execute(action_handler, "pkgadd -n -d \"#{remote_package_file}\" -a \"#{@tmp_dir}/nocheck\" chef")
179
+ when '.sh'
180
+ machine.execute(action_handler, "sh \"#{remote_package_file}\"")
181
+ else
182
+ raise "Unknown package extension '#{extension}' for file #{remote_package_file}"
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end