chef-metal 0.10.2 → 0.11.beta
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -5
- data/README.md +3 -3
- data/bin/metal +5 -9
- data/lib/chef/provider/machine.rb +81 -32
- data/lib/chef/provider/machine_batch.rb +67 -58
- data/lib/chef/provider/machine_execute.rb +7 -7
- data/lib/chef/provider/machine_file.rb +11 -11
- data/lib/chef/resource/machine.rb +11 -15
- data/lib/chef/resource/machine_batch.rb +1 -1
- data/lib/chef/resource/machine_execute.rb +3 -4
- data/lib/chef/resource/machine_file.rb +3 -4
- data/lib/chef_metal.rb +26 -28
- data/lib/chef_metal/action_handler.rb +9 -7
- data/lib/chef_metal/add_prefix_action_handler.rb +7 -5
- data/lib/chef_metal/chef_machine_spec.rb +64 -0
- data/lib/chef_metal/{provider_action_handler.rb → chef_provider_action_handler.rb} +27 -14
- data/lib/chef_metal/chef_run_data.rb +68 -7
- data/lib/chef_metal/convergence_strategy.rb +14 -3
- data/lib/chef_metal/convergence_strategy/install_cached.rb +24 -10
- data/lib/chef_metal/convergence_strategy/install_msi.rb +17 -10
- data/lib/chef_metal/convergence_strategy/install_sh.rb +20 -10
- data/lib/chef_metal/convergence_strategy/no_converge.rb +20 -13
- data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +51 -47
- data/lib/chef_metal/{provider.rb → driver.rb} +103 -79
- data/lib/chef_metal/machine.rb +13 -5
- data/lib/chef_metal/machine/basic_machine.rb +11 -11
- data/lib/chef_metal/machine/unix_machine.rb +6 -6
- data/lib/chef_metal/machine/windows_machine.rb +3 -3
- data/lib/chef_metal/machine_spec.rb +22 -25
- data/lib/chef_metal/recipe_dsl.rb +34 -9
- data/lib/chef_metal/transport.rb +7 -2
- data/lib/chef_metal/transport/ssh.rb +42 -9
- data/lib/chef_metal/transport/winrm.rb +8 -5
- data/lib/chef_metal/version.rb +1 -1
- data/spec/integration/machine.rb +29 -0
- metadata +21 -9
- data/lib/chef_metal/aws_credentials.rb +0 -58
- data/lib/chef_metal/openstack_credentials.rb +0 -44
- data/lib/chef_metal/provisioner.rb +0 -121
@@ -1,60 +1,70 @@
|
|
1
1
|
module ChefMetal
|
2
2
|
#
|
3
|
-
# A
|
3
|
+
# A Driver instance represents a place where machines can be created and found,
|
4
4
|
# and contains methods to create, delete, start, stop, and find them.
|
5
5
|
#
|
6
|
-
# For AWS, a
|
6
|
+
# For AWS, a Driver instance corresponds to a single account.
|
7
7
|
# For Vagrant, it is a directory where VM files are found.
|
8
8
|
#
|
9
|
-
# == How to Make a
|
9
|
+
# == How to Make a Driver
|
10
10
|
#
|
11
|
-
# To implement a
|
11
|
+
# To implement a Driver, you must implement the following methods:
|
12
12
|
#
|
13
13
|
# - initialize(driver_url) - create a new driver with the given URL
|
14
|
-
# - driver_url - a URL representing everything unique about your
|
14
|
+
# - driver_url - a URL representing everything unique about your driver.
|
15
15
|
# But NOT credentials.
|
16
16
|
# - allocate_machine - ask the driver to allocate a machine to you.
|
17
17
|
# - ready_machine - get the machine "ready" - wait for it to be booted and
|
18
18
|
# accessible (for example, accessible via SSH transport).
|
19
19
|
# - stop_machine - stop the machine.
|
20
|
-
# -
|
20
|
+
# - destroy_machine - delete the machine.
|
21
21
|
# - connect_to_machine - connect to the given machine.
|
22
22
|
#
|
23
23
|
# Optionally, you can also implement:
|
24
24
|
# - allocate_machines - allocate an entire group of machines.
|
25
|
-
# -
|
26
|
-
#
|
25
|
+
# - ready_machines - get a group of machines warm and booted.
|
26
|
+
# - stop_machines - stop a group of machines.
|
27
|
+
# - destroy_machines - delete a group of machines.
|
27
28
|
#
|
28
|
-
# Additionally, you must create a file named `chef_metal/
|
29
|
+
# Additionally, you must create a file named `chef_metal/driver_init/<scheme>.rb`,
|
29
30
|
# where <scheme> is the name of the scheme you chose for your driver_url. This
|
30
|
-
# file, when required, must call
|
31
|
+
# file, when required, must call ChefMetal.add_registered_driver(<scheme>, <class>).
|
32
|
+
# The given <class>.from_url(url, config) will be called with a driver_url and
|
33
|
+
# configuration.
|
31
34
|
#
|
32
35
|
# All of these methods must be idempotent - if the work is already done, they
|
33
36
|
# just don't do anything.
|
34
37
|
#
|
35
|
-
class
|
38
|
+
class Driver
|
36
39
|
#
|
37
|
-
# Inflate a driver from
|
38
|
-
# driver to figure out what the driver really needs, since it varies
|
39
|
-
# from driver to driver.
|
40
|
+
# Inflate a driver from a driver URL.
|
40
41
|
#
|
41
|
-
#
|
42
|
+
# == Parameters
|
42
43
|
# driver_url - the URL to inflate the driver
|
44
|
+
# config - a configuration hash. See "config" for a list of known keys.
|
43
45
|
#
|
44
|
-
#
|
45
|
-
# A
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
# == Returns
|
47
|
+
# A Driver representing the given driver_url.
|
48
|
+
#
|
49
|
+
def initialize(driver_url, config)
|
50
|
+
@driver_url = driver_url
|
51
|
+
@config = config
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Override this on specific driver classes
|
56
|
+
#
|
57
|
+
def self.from_url(driver_url, config)
|
58
|
+
ChefMetal.from_url(driver_url, config)
|
49
59
|
end
|
50
60
|
|
51
61
|
#
|
52
62
|
# A URL representing the driver and the place where machines come from.
|
53
|
-
# This will be stuffed in
|
54
|
-
# reinflated. URLs must have a unique scheme identifying the
|
55
|
-
# class, and enough information to identify the place where created
|
56
|
-
# can be found. For AWS, this is the account number; for lxc and
|
57
|
-
# it is the directory in which VMs and containers are.
|
63
|
+
# This will be stuffed in machine_spec.location['driver_url'] so that the
|
64
|
+
# machine can be reinflated. URLs must have a unique scheme identifying the
|
65
|
+
# driver class, and enough information to identify the place where created
|
66
|
+
# machines can be found. For AWS, this is the account number; for lxc and
|
67
|
+
# vagrant, it is the directory in which VMs and containers are.
|
58
68
|
#
|
59
69
|
# For example:
|
60
70
|
# - fog:AWS:123456789012
|
@@ -62,15 +72,31 @@ module ChefMetal
|
|
62
72
|
# - lxc:
|
63
73
|
# - docker:
|
64
74
|
#
|
65
|
-
|
66
|
-
|
75
|
+
attr_reader :driver_url
|
76
|
+
|
77
|
+
# A configuration hash. These keys may be present:
|
78
|
+
# - :driver_options: a driver-defined object containing driver config.
|
79
|
+
# - :private_keys: a hash of private keys, with a "name" and a "value". Values are either strings (paths) or PrivateKey objects.
|
80
|
+
# - :private_key_paths: a list of paths to directories containing private keys.
|
81
|
+
# - :write_private_key_path: the path to which we write new keys by default.
|
82
|
+
# - :log_level: :debug/:info/:warn/:error/:fatal
|
83
|
+
# - :chef_server_url: url to chef server
|
84
|
+
# - :node_name: username to talk to chef server
|
85
|
+
# - :client_key: path to key used to talk to chef server
|
86
|
+
attr_reader :config
|
87
|
+
|
88
|
+
#
|
89
|
+
# Driver configuration. Equivalent to config[:driver_options] || {}
|
90
|
+
#
|
91
|
+
def driver_options
|
92
|
+
config[:driver_options] || {}
|
67
93
|
end
|
68
94
|
|
69
95
|
#
|
70
|
-
# Allocate a machine from the PXE/cloud/VM/container
|
96
|
+
# Allocate a machine from the PXE/cloud/VM/container driver. This method
|
71
97
|
# does not need to wait for the machine to boot or have an IP, but it must
|
72
|
-
# store enough information in
|
73
|
-
#
|
98
|
+
# store enough information in machine_spec.location to find the machine
|
99
|
+
# later in ready_machine.
|
74
100
|
#
|
75
101
|
# If a machine is powered off or otherwise unusable, this method may start
|
76
102
|
# it, but does not need to wait until it is started. The idea is to get the
|
@@ -78,7 +104,7 @@ module ChefMetal
|
|
78
104
|
#
|
79
105
|
# ## Parameters
|
80
106
|
# action_handler - the action_handler object that is calling this method; this
|
81
|
-
# is generally a
|
107
|
+
# is generally a driver, but could be anything that can support the
|
82
108
|
# interface (i.e., in the case of the test kitchen metal driver for
|
83
109
|
# acquiring and destroying VMs).
|
84
110
|
#
|
@@ -86,13 +112,13 @@ module ChefMetal
|
|
86
112
|
#
|
87
113
|
# machine_options - a set of options representing the desired provisioning
|
88
114
|
# state of the machine (image name, bootstrap ssh credentials,
|
89
|
-
# etc.). This will NOT be stored in the
|
115
|
+
# etc.). This will NOT be stored in the machine_spec, and is
|
90
116
|
# ephemeral.
|
91
117
|
#
|
92
118
|
# ## Returns
|
93
119
|
#
|
94
120
|
# Modifies the passed-in machine_spec. Anything in here will be saved
|
95
|
-
# back
|
121
|
+
# back after allocate_machine completes.
|
96
122
|
#
|
97
123
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
98
124
|
raise "#{self.class} does not implement allocate_machine"
|
@@ -107,17 +133,21 @@ module ChefMetal
|
|
107
133
|
#
|
108
134
|
# ## Parameters
|
109
135
|
# action_handler - the action_handler object that is calling this method; this
|
110
|
-
# is generally a
|
136
|
+
# is generally a driver, but could be anything that can support the
|
111
137
|
# interface (i.e., in the case of the test kitchen metal driver for
|
112
138
|
# acquiring and destroying VMs).
|
113
139
|
# machine_spec - MachineSpec representing this machine.
|
140
|
+
# machine_options - a set of options representing the desired provisioning
|
141
|
+
# state of the machine (image name, bootstrap ssh credentials,
|
142
|
+
# etc.). This will NOT be stored in the machine_spec, and is
|
143
|
+
# ephemeral.
|
114
144
|
#
|
115
145
|
# ## Returns
|
116
146
|
#
|
117
147
|
# Machine object pointing at the machine, allowing useful actions like setup,
|
118
148
|
# converge, execute, file and directory.
|
119
149
|
#
|
120
|
-
def ready_machine(action_handler, machine_spec)
|
150
|
+
def ready_machine(action_handler, machine_spec, machine_options)
|
121
151
|
raise "#{self.class} does not implement ready_machine"
|
122
152
|
end
|
123
153
|
|
@@ -133,7 +163,7 @@ module ChefMetal
|
|
133
163
|
# Machine object pointing at the machine, allowing useful actions like setup,
|
134
164
|
# converge, execute, file and directory.
|
135
165
|
#
|
136
|
-
def connect_to_machine(machine_spec)
|
166
|
+
def connect_to_machine(machine_spec, machine_options)
|
137
167
|
raise "#{self.class} does not implement connect_to_machine"
|
138
168
|
end
|
139
169
|
|
@@ -141,14 +171,14 @@ module ChefMetal
|
|
141
171
|
# Delete the given machine (idempotent). Should destroy the machine,
|
142
172
|
# returning things to the state before allocate_machine was called.
|
143
173
|
#
|
144
|
-
def
|
145
|
-
raise "#{self.class} does not implement
|
174
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
175
|
+
raise "#{self.class} does not implement destroy_machine"
|
146
176
|
end
|
147
177
|
|
148
178
|
#
|
149
179
|
# Stop the given machine.
|
150
180
|
#
|
151
|
-
def stop_machine(action_handler, machine_spec)
|
181
|
+
def stop_machine(action_handler, machine_spec, machine_options)
|
152
182
|
raise "#{self.class} does not implement stop_machine"
|
153
183
|
end
|
154
184
|
|
@@ -158,21 +188,22 @@ module ChefMetal
|
|
158
188
|
|
159
189
|
#
|
160
190
|
# Allocate a set of machines. This should have the same effect as running
|
161
|
-
# allocate_machine on all
|
191
|
+
# allocate_machine on all machine_specs.
|
162
192
|
#
|
163
|
-
#
|
193
|
+
# Drivers do not need to implement this; the default implementation
|
164
194
|
# calls acquire_machine in parallel.
|
165
195
|
#
|
166
|
-
# ##
|
196
|
+
# ## Parameters
|
167
197
|
# action_handler - the action_handler object that is calling this method; this
|
168
|
-
# is generally a
|
198
|
+
# is generally a driver, but could be anything that can support the
|
169
199
|
# interface (i.e., in the case of the test kitchen metal driver for
|
170
200
|
# acquiring and destroying VMs).
|
171
|
-
#
|
201
|
+
# specs_and_options - a hash of machine_spec -> machine_options representing the
|
202
|
+
# machines to allocate.
|
172
203
|
# parallelizer - an object with a parallelize() method that works like this:
|
173
204
|
#
|
174
|
-
# parallelizer.parallelize(
|
175
|
-
# allocate_machine(action_handler,
|
205
|
+
# parallelizer.parallelize(specs_and_options) do |machine_spec|
|
206
|
+
# allocate_machine(action_handler, machine_spec)
|
176
207
|
# end.to_a
|
177
208
|
# # The to_a at the end causes you to wait until the parallelization is done
|
178
209
|
#
|
@@ -180,60 +211,53 @@ module ChefMetal
|
|
180
211
|
# not go over parallelization limits set by the user. Use of the parallelizer
|
181
212
|
# to parallelizer machines is not required.
|
182
213
|
#
|
183
|
-
|
184
|
-
|
185
|
-
|
214
|
+
# ## Block
|
215
|
+
#
|
216
|
+
# If you pass a block to this function, each machine will be yielded to you
|
217
|
+
# as it completes, and then the function will return when all machines are
|
218
|
+
# yielded.
|
219
|
+
#
|
220
|
+
# allocate_machines(action_handler, specs_and_options, parallelizer) do |machine_spec|
|
221
|
+
# ...
|
222
|
+
# end
|
223
|
+
#
|
224
|
+
def allocate_machines(action_handler, specs_and_options, parallelizer)
|
225
|
+
parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
|
226
|
+
allocate_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
|
186
227
|
yield machine_spec if block_given?
|
187
|
-
|
228
|
+
machine_spec
|
188
229
|
end.to_a
|
189
230
|
end
|
190
231
|
|
191
232
|
# Acquire machines in batch, in parallel if possible.
|
192
|
-
def
|
193
|
-
parallelizer.parallelize(
|
194
|
-
machine =
|
195
|
-
yield
|
233
|
+
def ready_machines(action_handler, specs_and_options, parallelizer)
|
234
|
+
parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
|
235
|
+
machine = ready_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
|
236
|
+
yield machine if block_given?
|
196
237
|
machine
|
197
238
|
end.to_a
|
198
239
|
end
|
199
240
|
|
200
241
|
# Stop machines in batch, in parallel if possible.
|
201
|
-
def stop_machines(action_handler,
|
202
|
-
parallelizer.parallelize(
|
203
|
-
stop_machine(add_prefix(machine_spec, action_handler), machine_spec)
|
242
|
+
def stop_machines(action_handler, specs_and_options, parallelizer)
|
243
|
+
parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
|
244
|
+
stop_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
|
204
245
|
yield machine_spec if block_given?
|
205
246
|
end.to_a
|
206
247
|
end
|
207
248
|
|
208
249
|
# Delete machines in batch, in parallel if possible.
|
209
|
-
def
|
210
|
-
parallelizer.parallelize(
|
211
|
-
|
250
|
+
def destroy_machines(action_handler, specs_and_options, parallelizer)
|
251
|
+
parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
|
252
|
+
destroy_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
|
212
253
|
yield machine_spec if block_given?
|
213
254
|
end.to_a
|
214
255
|
end
|
215
256
|
|
216
|
-
#
|
217
|
-
# Provider notification that happens at the point a machine resource is declared
|
218
|
-
# (after all properties have been set on it)
|
219
|
-
#
|
220
|
-
def resource_created(machine)
|
221
|
-
end
|
222
|
-
|
223
257
|
protected
|
224
258
|
|
225
|
-
def
|
226
|
-
|
227
|
-
ChefMetal.inline_resource(provider) do
|
228
|
-
chef_node node['name'] do
|
229
|
-
chef_server chef_server
|
230
|
-
raw_json node
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
def add_prefix(node_json, action_handler)
|
236
|
-
AddPrefixActionHandler.new(action_handler, "[#{node_json['name']}] ")
|
259
|
+
def add_prefix(machine_spec, action_handler)
|
260
|
+
AddPrefixActionHandler.new(action_handler, "[#{machine_spec.name}] ")
|
237
261
|
end
|
238
262
|
end
|
239
263
|
end
|
data/lib/chef_metal/machine.rb
CHANGED
@@ -1,19 +1,27 @@
|
|
1
1
|
module ChefMetal
|
2
2
|
class Machine
|
3
|
-
def initialize(
|
4
|
-
@
|
3
|
+
def initialize(machine_spec)
|
4
|
+
@machine_spec = machine_spec
|
5
5
|
end
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :machine_spec
|
8
|
+
|
9
|
+
def name
|
10
|
+
machine_spec.name
|
11
|
+
end
|
12
|
+
|
13
|
+
def node
|
14
|
+
machine_spec.node
|
15
|
+
end
|
8
16
|
|
9
17
|
# Sets up everything necessary for convergence to happen on the machine.
|
10
18
|
# The node MUST be saved as part of this procedure. Other than that,
|
11
19
|
# nothing is guaranteed except that converge() will work when this is done.
|
12
|
-
def setup_convergence(action_handler
|
20
|
+
def setup_convergence(action_handler)
|
13
21
|
raise "setup_convergence not overridden on #{self.class}"
|
14
22
|
end
|
15
23
|
|
16
|
-
def converge(action_handler
|
24
|
+
def converge(action_handler)
|
17
25
|
raise "converge not overridden on #{self.class}"
|
18
26
|
end
|
19
27
|
|
@@ -3,8 +3,8 @@ require 'chef_metal/machine'
|
|
3
3
|
module ChefMetal
|
4
4
|
class Machine
|
5
5
|
class BasicMachine < Machine
|
6
|
-
def initialize(
|
7
|
-
super(
|
6
|
+
def initialize(machine_spec, transport, convergence_strategy)
|
7
|
+
super(machine_spec)
|
8
8
|
@transport = transport
|
9
9
|
@convergence_strategy = convergence_strategy
|
10
10
|
end
|
@@ -13,18 +13,18 @@ module ChefMetal
|
|
13
13
|
attr_reader :convergence_strategy
|
14
14
|
|
15
15
|
# Sets up everything necessary for convergence to happen on the machine.
|
16
|
-
# The
|
16
|
+
# The machine_spec MUST be saved as part of this procedure. Other than that,
|
17
17
|
# nothing is guaranteed except that converge() will work when this is done.
|
18
|
-
def setup_convergence(action_handler
|
19
|
-
convergence_strategy.setup_convergence(action_handler, self
|
18
|
+
def setup_convergence(action_handler)
|
19
|
+
convergence_strategy.setup_convergence(action_handler, self)
|
20
20
|
end
|
21
21
|
|
22
|
-
def converge(action_handler
|
23
|
-
convergence_strategy.converge(action_handler, self
|
22
|
+
def converge(action_handler)
|
23
|
+
convergence_strategy.converge(action_handler, self)
|
24
24
|
end
|
25
25
|
|
26
26
|
def execute(action_handler, command, options = {})
|
27
|
-
action_handler.perform_action "run '#{command}' on #{
|
27
|
+
action_handler.perform_action "run '#{command}' on #{machine_spec.name}" do
|
28
28
|
result = transport.execute(command, options)
|
29
29
|
result.error!
|
30
30
|
result
|
@@ -41,7 +41,7 @@ module ChefMetal
|
|
41
41
|
|
42
42
|
def download_file(action_handler, path, local_path)
|
43
43
|
if files_different?(path, local_path)
|
44
|
-
action_handler.perform_action "download file #{path} on #{
|
44
|
+
action_handler.perform_action "download file #{path} on #{machine_spec.name} to #{local_path}" do
|
45
45
|
transport.download_file(path, local_path)
|
46
46
|
end
|
47
47
|
end
|
@@ -52,7 +52,7 @@ module ChefMetal
|
|
52
52
|
if options[:ensure_dir]
|
53
53
|
create_dir(action_handler, dirname_on_machine(path))
|
54
54
|
end
|
55
|
-
action_handler.perform_action "write file #{path} on #{
|
55
|
+
action_handler.perform_action "write file #{path} on #{machine_spec.name}" do
|
56
56
|
transport.write_file(path, content)
|
57
57
|
end
|
58
58
|
end
|
@@ -63,7 +63,7 @@ module ChefMetal
|
|
63
63
|
if options[:ensure_dir]
|
64
64
|
create_dir(action_handler, dirname_on_machine(path))
|
65
65
|
end
|
66
|
-
action_handler.perform_action "upload file #{local_path} to #{path} on #{
|
66
|
+
action_handler.perform_action "upload file #{local_path} to #{path} on #{machine_spec.name}" do
|
67
67
|
transport.upload_file(local_path, path)
|
68
68
|
end
|
69
69
|
end
|
@@ -4,7 +4,7 @@ require 'digest'
|
|
4
4
|
module ChefMetal
|
5
5
|
class Machine
|
6
6
|
class UnixMachine < BasicMachine
|
7
|
-
def initialize(
|
7
|
+
def initialize(machine_spec, transport, convergence_strategy)
|
8
8
|
super
|
9
9
|
|
10
10
|
@tmp_dir = '/tmp'
|
@@ -18,7 +18,7 @@ module ChefMetal
|
|
18
18
|
# Delete file
|
19
19
|
def delete_file(action_handler, path)
|
20
20
|
if file_exists?(path)
|
21
|
-
action_handler.perform_action "delete file #{path} on #{
|
21
|
+
action_handler.perform_action "delete file #{path} on #{machine_spec.name}" do
|
22
22
|
transport.execute("rm -f #{path}").error!
|
23
23
|
end
|
24
24
|
end
|
@@ -61,7 +61,7 @@ module ChefMetal
|
|
61
61
|
|
62
62
|
def create_dir(action_handler, path)
|
63
63
|
if !file_exists?(path)
|
64
|
-
action_handler.perform_action "create directory #{path} on #{
|
64
|
+
action_handler.perform_action "create directory #{path} on #{machine_spec.name}" do
|
65
65
|
transport.execute("mkdir -p #{path}").error!
|
66
66
|
end
|
67
67
|
end
|
@@ -72,17 +72,17 @@ module ChefMetal
|
|
72
72
|
if attributes[:mode] || attributes[:owner] || attributes[:group]
|
73
73
|
current_attributes = get_attributes(path)
|
74
74
|
if attributes[:mode] && current_attributes[:mode].to_i != attributes[:mode].to_i
|
75
|
-
action_handler.perform_action "change mode of #{path} on #{
|
75
|
+
action_handler.perform_action "change mode of #{path} on #{machine_spec.name} from #{current_attributes[:mode].to_i} to #{attributes[:mode].to_i}" do
|
76
76
|
transport.execute("chmod #{attributes[:mode].to_i} #{path}").error!
|
77
77
|
end
|
78
78
|
end
|
79
79
|
if attributes[:owner] && current_attributes[:owner] != attributes[:owner]
|
80
|
-
action_handler.perform_action "change group of #{path} on #{
|
80
|
+
action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
|
81
81
|
transport.execute("chown #{attributes[:owner]} #{path}").error!
|
82
82
|
end
|
83
83
|
end
|
84
84
|
if attributes[:group] && current_attributes[:group] != attributes[:group]
|
85
|
-
action_handler.perform_action "change group of #{path} on #{
|
85
|
+
action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:group]} to #{attributes[:group]}" do
|
86
86
|
transport.execute("chgrp #{attributes[:group]} #{path}").error!
|
87
87
|
end
|
88
88
|
end
|