chef-provisioning 2.0.1 → 2.0.2

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 +906 -899
  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 -36
  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 -144
  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 -30
  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 +10 -4
@@ -1,144 +1,144 @@
1
- require 'chef/provisioning/transport'
2
- require 'base64'
3
- require 'timeout'
4
-
5
- class Chef
6
- module Provisioning
7
- class Transport
8
- # Transport to handle the WinRM connection protocol.
9
- class WinRM < Chef::Provisioning::Transport
10
- #
11
- # Create a new WinRM transport.
12
- #
13
- # == Arguments
14
- # - endpoint: the WinRM endpoint, e.g. http://145.14.51.45:5985/wsman.
15
- # - type: the connection type, e.g. :plaintext.
16
- # - options: options hash, including both WinRM options and transport options.
17
- # For transport options, see the Transport.options definition. WinRM
18
- # options include :user, :pass, :disable_sspi => true, among others.
19
- # - global_config: an options hash that looks suspiciously similar to
20
- # Chef::Config, containing at least the key :log_level.
21
- #
22
- # The actual connection is made as ::WinRM::WinRMWebService.new(endpoint, type, options)
23
- #
24
- def initialize(endpoint, type, options, global_config)
25
- @options = options
26
- @options[:endpoint] = endpoint
27
- @options[:transport] = type
28
-
29
- # WinRM v2 switched from :pass to :password
30
- # we accept either to avoid having to update every driver
31
- @options[:password] = @options[:password] || @options[:pass]
32
-
33
- @config = global_config
34
- end
35
-
36
- attr_reader :options
37
- attr_reader :config
38
-
39
- def execute(command, execute_options = {})
40
- output = with_execute_timeout(execute_options) do
41
- block = Proc.new { |stdout, stderr| stream_chunk(execute_options, stdout, stderr) }
42
- session.run(command, &block)
43
- end
44
- WinRMResult.new(command, execute_options, config, output)
45
- end
46
-
47
- def read_file(path)
48
- result = execute("[Convert]::ToBase64String((Get-Content #{escape(path)} -Encoding byte -ReadCount 0))")
49
- if result.exitstatus == 0
50
- Base64.decode64(result.stdout)
51
- else
52
- nil
53
- end
54
- end
55
-
56
- def write_file(path, content)
57
- file = Tempfile.new('provisioning-upload')
58
- begin
59
- file.write(content)
60
- file.close
61
- file_transporter.upload(file.path, path)
62
- ensure
63
- file.unlink
64
- end
65
- end
66
-
67
- def disconnect
68
- #
69
- end
70
-
71
- def escape(string)
72
- "\"#{string.gsub("\"", "`\"")}\""
73
- end
74
-
75
- def available?
76
- # If you can't pwd within 10 seconds, you can't pwd
77
- execute('pwd', :timeout => 10)
78
- true
79
- rescue ::WinRM::WinRMAuthorizationError
80
- Chef::Log.debug("unavailable: winrm authentication error: #{$!.inspect} ")
81
- disconnect
82
- false
83
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, ::WinRM::WinRMError
84
- Chef::Log.debug("unavailable: network connection failed or broke: #{$!.inspect}")
85
- disconnect
86
- false
87
- end
88
-
89
- def make_url_available_to_remote(local_url)
90
- uri = URI(local_url)
91
- uri.scheme = 'http' if uri.scheme == 'chefzero' && uri.host == 'localhost'
92
- host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
93
- if host == '127.0.0.1' || host == '::1'
94
- raise 'Unable to converge locally via winrm. Local converge is currently only supported with SSH. You may only converge with winrm against a chef-server.'
95
- end
96
- local_url
97
- end
98
-
99
- protected
100
-
101
- def session
102
- @session ||= begin
103
- require 'winrm'
104
- ::WinRM::Connection.new(options).shell(:powershell)
105
- end
106
- end
107
-
108
- def file_transporter
109
- @file_transporter ||= begin
110
- require 'winrm-fs'
111
- ::WinRM::FS::Core::FileTransporter.new(session)
112
- end
113
- end
114
-
115
- class WinRMResult
116
- def initialize(command, options, config, output)
117
- @command = command
118
- @options = options
119
- @config = config
120
- @exitstatus = output.exitcode
121
- @stdout = output.stdout
122
- @stderr = output.stderr
123
- end
124
-
125
- attr_reader :stdout
126
- attr_reader :stderr
127
- attr_reader :exitstatus
128
- attr_reader :command
129
- attr_reader :options
130
- attr_reader :config
131
-
132
- def error!
133
- if exitstatus != 0
134
- msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
135
- msg << "STDOUT: #{stdout}" if !options[:stream] && !options[:stream_stdout] && config[:log_level] != :debug
136
- msg << "STDERR: #{stderr}" if !options[:stream] && !options[:stream_stderr] && config[:log_level] != :debug
137
- raise msg
138
- end
139
- end
140
- end
141
- end
142
- end
143
- end
144
- end
1
+ require 'chef/provisioning/transport'
2
+ require 'base64'
3
+ require 'timeout'
4
+
5
+ class Chef
6
+ module Provisioning
7
+ class Transport
8
+ # Transport to handle the WinRM connection protocol.
9
+ class WinRM < Chef::Provisioning::Transport
10
+ #
11
+ # Create a new WinRM transport.
12
+ #
13
+ # == Arguments
14
+ # - endpoint: the WinRM endpoint, e.g. http://145.14.51.45:5985/wsman.
15
+ # - type: the connection type, e.g. :plaintext.
16
+ # - options: options hash, including both WinRM options and transport options.
17
+ # For transport options, see the Transport.options definition. WinRM
18
+ # options include :user, :pass, :disable_sspi => true, among others.
19
+ # - global_config: an options hash that looks suspiciously similar to
20
+ # Chef::Config, containing at least the key :log_level.
21
+ #
22
+ # The actual connection is made as ::WinRM::WinRMWebService.new(endpoint, type, options)
23
+ #
24
+ def initialize(endpoint, type, options, global_config)
25
+ @options = options
26
+ @options[:endpoint] = endpoint
27
+ @options[:transport] = type
28
+
29
+ # WinRM v2 switched from :pass to :password
30
+ # we accept either to avoid having to update every driver
31
+ @options[:password] = @options[:password] || @options[:pass]
32
+
33
+ @config = global_config
34
+ end
35
+
36
+ attr_reader :options
37
+ attr_reader :config
38
+
39
+ def execute(command, execute_options = {})
40
+ output = with_execute_timeout(execute_options) do
41
+ block = Proc.new { |stdout, stderr| stream_chunk(execute_options, stdout, stderr) }
42
+ session.run(command, &block)
43
+ end
44
+ WinRMResult.new(command, execute_options, config, output)
45
+ end
46
+
47
+ def read_file(path)
48
+ result = execute("[Convert]::ToBase64String((Get-Content #{escape(path)} -Encoding byte -ReadCount 0))")
49
+ if result.exitstatus == 0
50
+ Base64.decode64(result.stdout)
51
+ else
52
+ nil
53
+ end
54
+ end
55
+
56
+ def write_file(path, content)
57
+ file = Tempfile.new('provisioning-upload')
58
+ begin
59
+ file.write(content)
60
+ file.close
61
+ file_transporter.upload(file.path, path)
62
+ ensure
63
+ file.unlink
64
+ end
65
+ end
66
+
67
+ def disconnect
68
+ #
69
+ end
70
+
71
+ def escape(string)
72
+ "\"#{string.gsub("\"", "`\"")}\""
73
+ end
74
+
75
+ def available?
76
+ # If you can't pwd within 10 seconds, you can't pwd
77
+ execute('pwd', :timeout => 10)
78
+ true
79
+ rescue ::WinRM::WinRMAuthorizationError
80
+ Chef::Log.debug("unavailable: winrm authentication error: #{$!.inspect} ")
81
+ disconnect
82
+ false
83
+ rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, ::WinRM::WinRMError
84
+ Chef::Log.debug("unavailable: network connection failed or broke: #{$!.inspect}")
85
+ disconnect
86
+ false
87
+ end
88
+
89
+ def make_url_available_to_remote(local_url)
90
+ uri = URI(local_url)
91
+ uri.scheme = 'http' if uri.scheme == 'chefzero' && uri.host == 'localhost'
92
+ host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
93
+ if host == '127.0.0.1' || host == '::1'
94
+ raise 'Unable to converge locally via winrm. Local converge is currently only supported with SSH. You may only converge with winrm against a chef-server.'
95
+ end
96
+ local_url
97
+ end
98
+
99
+ protected
100
+
101
+ def session
102
+ @session ||= begin
103
+ require 'winrm'
104
+ ::WinRM::Connection.new(options).shell(:powershell)
105
+ end
106
+ end
107
+
108
+ def file_transporter
109
+ @file_transporter ||= begin
110
+ require 'winrm-fs'
111
+ ::WinRM::FS::Core::FileTransporter.new(session)
112
+ end
113
+ end
114
+
115
+ class WinRMResult
116
+ def initialize(command, options, config, output)
117
+ @command = command
118
+ @options = options
119
+ @config = config
120
+ @exitstatus = output.exitcode
121
+ @stdout = output.stdout
122
+ @stderr = output.stderr
123
+ end
124
+
125
+ attr_reader :stdout
126
+ attr_reader :stderr
127
+ attr_reader :exitstatus
128
+ attr_reader :command
129
+ attr_reader :options
130
+ attr_reader :config
131
+
132
+ def error!
133
+ if exitstatus != 0
134
+ msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
135
+ msg << "STDOUT: #{stdout}" if !options[:stream] && !options[:stream_stdout] && config[:log_level] != :debug
136
+ msg << "STDERR: #{stderr}" if !options[:stream] && !options[:stream_stderr] && config[:log_level] != :debug
137
+ raise msg
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -1,5 +1,5 @@
1
- class Chef
2
- module Provisioning
3
- VERSION = '2.0.1'
4
- end
5
- end
1
+ class Chef
2
+ module Provisioning
3
+ VERSION = '2.0.2'
4
+ end
5
+ end
@@ -1,146 +1,146 @@
1
- require 'chef/resource/lwrp_base'
2
- require 'cheffish'
3
-
4
- # A resource that is backed by a data bag in a Chef server somewhere
5
- class Chef::Resource::ChefDataBagResource < Chef::Resource::LWRPBase
6
-
7
- # The key to store this thing under (/data/bag/<<name>>).
8
- attr_reader :name
9
-
10
- class << self
11
- # The name of the databag to store the item in.
12
- attr_reader :databag_name
13
- end
14
-
15
- def initialize(name, run_context=nil)
16
- super
17
- Chef::Log.debug("Re-hydrating #{name} from #{self.class.databag_name}...")
18
- self.hydrate
19
- end
20
-
21
- # A list of attributes to be persisted into the databag.
22
- # @return [Array] List of attributes that are stored in the databag
23
- def self.stored_attributes
24
- @stored_attributes || []
25
- end
26
-
27
- # Set databag name
28
- # @return [Void]
29
- def self.databag_name= name
30
- Chef::Log.debug("Setting databag name to #{name}")
31
- @databag_name = name
32
- end
33
-
34
- # Mark an attribute as stored by adding it to the internal tracking list {stored_attributes}
35
- # and then delegating to {Chef::Resource::LWRPBase#attribute}
36
- # @param attr_name [Symbol] Name of the attribute as a symbol
37
- # @return [Void]
38
- def self.stored_attribute(attr_name, *args)
39
- @stored_attributes ||= []
40
- @stored_attributes << attr_name
41
- self.attribute attr_name, *args
42
- end
43
-
44
- # Load persisted data from the server's databag. If the databag does not exist on the
45
- # server, returns nil.
46
- #
47
- # @param chef_server [Hash] A hash representing which Chef server to talk to
48
- # @option chef_server [String] :chef_server_url URL to the Chef server
49
- # @option chef_server [Hash] :options Options for when talking to the Chef server
50
- # @option options [String] :client_name The node name making the call
51
- # @option options [String] :signing_key_filename Path to the signing key
52
- # @return [Object] an instance of this class re-hydrated from the data hash stored in the
53
- # databag.
54
- def hydrate(chef_server = Cheffish.default_chef_server)
55
- chef_api = Cheffish.chef_server_api(chef_server)
56
- begin
57
- data = chef_api.get("/data/#{self.class.databag_name}/#{name}")
58
- load_from_hash(data)
59
- Chef::Log.debug("Rehydrating resource from #{self.class.databag_name}/#{name}: #{data}")
60
- rescue Net::HTTPServerException => e
61
- if e.response.code == '404'
62
- nil
63
- else
64
- raise
65
- end
66
- end
67
- end
68
-
69
- # Load instance variable data from a hash. For each key,value pair, set @<key> to value
70
- # @param hash [Hash] Hash containing the instance variable data
71
- # @return [Object] self after having been populated with data.
72
- def load_from_hash hash
73
- hash.each do |k,v|
74
- self.instance_variable_set("@#{k}", v)
75
- end
76
- self
77
- end
78
-
79
- # Convert the values in {stored_attributes} to a hash for storing in a databag
80
- # @return [Hash] a hash of (k,v) pairs where k is each record in {stored_attributes}
81
- def storage_hash
82
- ignored = []
83
-
84
- hash = {}
85
- (self.class.stored_attributes - ignored).each do |attr_name|
86
- varname = "@#{attr_name.to_s.gsub('@', '')}"
87
- key = varname.gsub('@', '')
88
- hash[key] = self.instance_variable_get varname
89
- end
90
-
91
- hash
92
- end
93
-
94
-
95
- # Save this entity to the server. If you have significant information that
96
- # could be lost, you should do this as quickly as possible.
97
- # @return [Void]
98
- def save
99
-
100
- create_databag_if_needed self.class.databag_name
101
-
102
- # Clone for inline_resource
103
- _databag_name = self.class.databag_name
104
- _hash = self.storage_hash
105
- _name = self.name
106
-
107
- Cheffish.inline_resource(self, @action) do
108
- chef_data_bag_item _name do
109
- data_bag _databag_name
110
- raw_data _hash
111
- action :create
112
- end
113
- end
114
- end
115
-
116
- # Delete this entity from the server
117
- # @return [Void]
118
- def delete
119
- # Clone for inline_resource
120
- _name = self.name
121
- _databag_name = self.class.databag_name
122
-
123
- Cheffish.inline_resource(self, @action) do
124
- chef_data_bag_item _name do
125
- data_bag _databag_name
126
- action :delete
127
- end
128
- end
129
- end
130
-
131
- def new_resource
132
- self
133
- end
134
-
135
- private
136
- # Create the databag with Cheffish if required
137
- # @return [Void]
138
- def create_databag_if_needed databag_name
139
- _databag_name = databag_name
140
- Cheffish.inline_resource(self, @action) do
141
- chef_data_bag _databag_name do
142
- action :create
143
- end
144
- end
145
- end
146
- end
1
+ require 'chef/resource/lwrp_base'
2
+ require 'cheffish'
3
+
4
+ # A resource that is backed by a data bag in a Chef server somewhere
5
+ class Chef::Resource::ChefDataBagResource < Chef::Resource::LWRPBase
6
+
7
+ # The key to store this thing under (/data/bag/<<name>>).
8
+ attr_reader :name
9
+
10
+ class << self
11
+ # The name of the databag to store the item in.
12
+ attr_reader :databag_name
13
+ end
14
+
15
+ def initialize(name, run_context=nil)
16
+ super
17
+ Chef::Log.debug("Re-hydrating #{name} from #{self.class.databag_name}...")
18
+ self.hydrate
19
+ end
20
+
21
+ # A list of attributes to be persisted into the databag.
22
+ # @return [Array] List of attributes that are stored in the databag
23
+ def self.stored_attributes
24
+ @stored_attributes || []
25
+ end
26
+
27
+ # Set databag name
28
+ # @return [Void]
29
+ def self.databag_name= name
30
+ Chef::Log.debug("Setting databag name to #{name}")
31
+ @databag_name = name
32
+ end
33
+
34
+ # Mark an attribute as stored by adding it to the internal tracking list {stored_attributes}
35
+ # and then delegating to {Chef::Resource::LWRPBase#attribute}
36
+ # @param attr_name [Symbol] Name of the attribute as a symbol
37
+ # @return [Void]
38
+ def self.stored_attribute(attr_name, *args)
39
+ @stored_attributes ||= []
40
+ @stored_attributes << attr_name
41
+ self.attribute attr_name, *args
42
+ end
43
+
44
+ # Load persisted data from the server's databag. If the databag does not exist on the
45
+ # server, returns nil.
46
+ #
47
+ # @param chef_server [Hash] A hash representing which Chef server to talk to
48
+ # @option chef_server [String] :chef_server_url URL to the Chef server
49
+ # @option chef_server [Hash] :options Options for when talking to the Chef server
50
+ # @option options [String] :client_name The node name making the call
51
+ # @option options [String] :signing_key_filename Path to the signing key
52
+ # @return [Object] an instance of this class re-hydrated from the data hash stored in the
53
+ # databag.
54
+ def hydrate(chef_server = Cheffish.default_chef_server)
55
+ chef_api = Cheffish.chef_server_api(chef_server)
56
+ begin
57
+ data = chef_api.get("/data/#{self.class.databag_name}/#{name}")
58
+ load_from_hash(data)
59
+ Chef::Log.debug("Rehydrating resource from #{self.class.databag_name}/#{name}: #{data}")
60
+ rescue Net::HTTPServerException => e
61
+ if e.response.code == '404'
62
+ nil
63
+ else
64
+ raise
65
+ end
66
+ end
67
+ end
68
+
69
+ # Load instance variable data from a hash. For each key,value pair, set @<key> to value
70
+ # @param hash [Hash] Hash containing the instance variable data
71
+ # @return [Object] self after having been populated with data.
72
+ def load_from_hash hash
73
+ hash.each do |k,v|
74
+ self.instance_variable_set("@#{k}", v)
75
+ end
76
+ self
77
+ end
78
+
79
+ # Convert the values in {stored_attributes} to a hash for storing in a databag
80
+ # @return [Hash] a hash of (k,v) pairs where k is each record in {stored_attributes}
81
+ def storage_hash
82
+ ignored = []
83
+
84
+ hash = {}
85
+ (self.class.stored_attributes - ignored).each do |attr_name|
86
+ varname = "@#{attr_name.to_s.gsub('@', '')}"
87
+ key = varname.gsub('@', '')
88
+ hash[key] = self.instance_variable_get varname
89
+ end
90
+
91
+ hash
92
+ end
93
+
94
+
95
+ # Save this entity to the server. If you have significant information that
96
+ # could be lost, you should do this as quickly as possible.
97
+ # @return [Void]
98
+ def save
99
+
100
+ create_databag_if_needed self.class.databag_name
101
+
102
+ # Clone for inline_resource
103
+ _databag_name = self.class.databag_name
104
+ _hash = self.storage_hash
105
+ _name = self.name
106
+
107
+ Cheffish.inline_resource(self, @action) do
108
+ chef_data_bag_item _name do
109
+ data_bag _databag_name
110
+ raw_data _hash
111
+ action :create
112
+ end
113
+ end
114
+ end
115
+
116
+ # Delete this entity from the server
117
+ # @return [Void]
118
+ def delete
119
+ # Clone for inline_resource
120
+ _name = self.name
121
+ _databag_name = self.class.databag_name
122
+
123
+ Cheffish.inline_resource(self, @action) do
124
+ chef_data_bag_item _name do
125
+ data_bag _databag_name
126
+ action :delete
127
+ end
128
+ end
129
+ end
130
+
131
+ def new_resource
132
+ self
133
+ end
134
+
135
+ private
136
+ # Create the databag with Cheffish if required
137
+ # @return [Void]
138
+ def create_databag_if_needed databag_name
139
+ _databag_name = databag_name
140
+ Cheffish.inline_resource(self, @action) do
141
+ chef_data_bag _databag_name do
142
+ action :create
143
+ end
144
+ end
145
+ end
146
+ end