chef-metal 0.14.2 → 0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/README.md +2 -257
  4. data/Rakefile +0 -4
  5. data/lib/chef_metal.rb +1 -87
  6. data/lib/chef_metal/action_handler.rb +1 -66
  7. data/lib/chef_metal/add_prefix_action_handler.rb +1 -29
  8. data/lib/chef_metal/chef_image_spec.rb +1 -106
  9. data/lib/chef_metal/chef_machine_spec.rb +1 -82
  10. data/lib/chef_metal/chef_provider_action_handler.rb +1 -72
  11. data/lib/chef_metal/chef_run_data.rb +1 -125
  12. data/lib/chef_metal/convergence_strategy.rb +1 -26
  13. data/lib/chef_metal/convergence_strategy/install_cached.rb +1 -157
  14. data/lib/chef_metal/convergence_strategy/install_msi.rb +1 -56
  15. data/lib/chef_metal/convergence_strategy/install_sh.rb +1 -53
  16. data/lib/chef_metal/convergence_strategy/no_converge.rb +1 -37
  17. data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +1 -181
  18. data/lib/chef_metal/driver.rb +1 -288
  19. data/lib/chef_metal/image_spec.rb +1 -70
  20. data/lib/chef_metal/machine.rb +1 -110
  21. data/lib/chef_metal/machine/basic_machine.rb +1 -82
  22. data/lib/chef_metal/machine/unix_machine.rb +1 -276
  23. data/lib/chef_metal/machine/windows_machine.rb +1 -102
  24. data/lib/chef_metal/machine_spec.rb +1 -78
  25. data/lib/chef_metal/recipe_dsl.rb +1 -94
  26. data/lib/chef_metal/transport.rb +1 -87
  27. data/lib/chef_metal/transport/ssh.rb +1 -288
  28. data/lib/chef_metal/transport/winrm.rb +1 -134
  29. data/lib/chef_metal/version.rb +1 -3
  30. metadata +19 -145
  31. data/bin/metal +0 -275
  32. data/lib/chef/provider/machine.rb +0 -171
  33. data/lib/chef/provider/machine_batch.rb +0 -186
  34. data/lib/chef/provider/machine_execute.rb +0 -30
  35. data/lib/chef/provider/machine_file.rb +0 -49
  36. data/lib/chef/provider/machine_image.rb +0 -54
  37. data/lib/chef/resource/machine.rb +0 -116
  38. data/lib/chef/resource/machine_batch.rb +0 -72
  39. data/lib/chef/resource/machine_execute.rb +0 -22
  40. data/lib/chef/resource/machine_file.rb +0 -28
  41. data/lib/chef/resource/machine_image.rb +0 -29
@@ -1,288 +1 @@
1
- module ChefMetal
2
- #
3
- # A Driver instance represents a place where machines can be created and found,
4
- # and contains methods to create, delete, start, stop, and find them.
5
- #
6
- # For AWS, a Driver instance corresponds to a single account.
7
- # For Vagrant, it is a directory where VM files are found.
8
- #
9
- # == How to Make a Driver
10
- #
11
- # To implement a Driver, you must implement the following methods:
12
- #
13
- # - initialize(driver_url) - create a new driver with the given URL
14
- # - driver_url - a URL representing everything unique about your driver.
15
- # But NOT credentials.
16
- # - allocate_machine - ask the driver to allocate a machine to you.
17
- # - ready_machine - get the machine "ready" - wait for it to be booted and
18
- # accessible (for example, accessible via SSH transport).
19
- # - stop_machine - stop the machine.
20
- # - destroy_machine - delete the machine.
21
- # - connect_to_machine - connect to the given machine.
22
- #
23
- # Optionally, you can also implement:
24
- # - allocate_machines - allocate an entire group of machines.
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.
28
- #
29
- # Additionally, you must create a file named `chef_metal/driver_init/<scheme>.rb`,
30
- # where <scheme> is the name of the scheme you chose for your driver_url. This
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.
34
- #
35
- # All of these methods must be idempotent - if the work is already done, they
36
- # just don't do anything.
37
- #
38
- class Driver
39
- #
40
- # Inflate a driver from a driver URL.
41
- #
42
- # == Parameters
43
- # driver_url - the URL to inflate the driver
44
- # config - a configuration hash. See "config" for a list of known keys.
45
- #
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)
59
- end
60
-
61
- #
62
- # A URL representing the driver and the place where machines come from.
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.
68
- #
69
- # For example:
70
- # - fog:AWS:123456789012
71
- # - vagrant:/var/vms
72
- # - lxc:
73
- # - docker:
74
- #
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] || {}
93
- end
94
-
95
- #
96
- # Allocate a machine from the PXE/cloud/VM/container driver. This method
97
- # does not need to wait for the machine to boot or have an IP, but it must
98
- # store enough information in machine_spec.location to find the machine
99
- # later in ready_machine.
100
- #
101
- # If a machine is powered off or otherwise unusable, this method may start
102
- # it, but does not need to wait until it is started. The idea is to get the
103
- # gears moving, but the job doesn't need to be done :)
104
- #
105
- # ## Parameters
106
- # action_handler - the action_handler object that is calling this method; this
107
- # is generally a driver, but could be anything that can support the
108
- # interface (i.e., in the case of the test kitchen metal driver for
109
- # acquiring and destroying VMs).
110
- #
111
- # existing_machine - a MachineSpec representing the existing machine (if any).
112
- #
113
- # machine_options - a set of options representing the desired provisioning
114
- # state of the machine (image name, bootstrap ssh credentials,
115
- # etc.). This will NOT be stored in the machine_spec, and is
116
- # ephemeral.
117
- #
118
- # ## Returns
119
- #
120
- # Modifies the passed-in machine_spec. Anything in here will be saved
121
- # back after allocate_machine completes.
122
- #
123
- def allocate_machine(action_handler, machine_spec, machine_options)
124
- raise "#{self.class} does not implement allocate_machine"
125
- end
126
-
127
- #
128
- # Ready a machine, to the point where it is running and accessible via a
129
- # transport. This will NOT allocate a machine, but may kick it if it is down.
130
- # This method waits for the machine to be usable, returning a Machine object
131
- # pointing at the machine, allowing useful actions like setup, converge,
132
- # execute, file and directory.
133
- #
134
- # ## Parameters
135
- # action_handler - the action_handler object that is calling this method; this
136
- # is generally a driver, but could be anything that can support the
137
- # interface (i.e., in the case of the test kitchen metal driver for
138
- # acquiring and destroying VMs).
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.
144
- #
145
- # ## Returns
146
- #
147
- # Machine object pointing at the machine, allowing useful actions like setup,
148
- # converge, execute, file and directory.
149
- #
150
- def ready_machine(action_handler, machine_spec, machine_options)
151
- raise "#{self.class} does not implement ready_machine"
152
- end
153
-
154
- #
155
- # Connect to a machine without allocating or readying it. This method will
156
- # NOT make any changes to anything, or attempt to wait.
157
- #
158
- # ## Parameters
159
- # machine_spec - MachineSpec representing this machine.
160
- #
161
- # ## Returns
162
- #
163
- # Machine object pointing at the machine, allowing useful actions like setup,
164
- # converge, execute, file and directory.
165
- #
166
- def connect_to_machine(machine_spec, machine_options)
167
- raise "#{self.class} does not implement connect_to_machine"
168
- end
169
-
170
- #
171
- # Delete the given machine (idempotent). Should destroy the machine,
172
- # returning things to the state before allocate_machine was called.
173
- #
174
- def destroy_machine(action_handler, machine_spec, machine_options)
175
- raise "#{self.class} does not implement destroy_machine"
176
- end
177
-
178
- #
179
- # Stop the given machine.
180
- #
181
- def stop_machine(action_handler, machine_spec, machine_options)
182
- raise "#{self.class} does not implement stop_machine"
183
- end
184
-
185
- #
186
- # Allocate an image. Returns quickly with an ID that tracks the image.
187
- #
188
- def allocate_image(action_handler, image_spec, image_options, machine_spec)
189
- raise "#{self.class} does not implement create_image"
190
- end
191
-
192
- #
193
- # Ready an image, waiting till the point where it is ready to be used.
194
- #
195
- def ready_image(action_handler, image_spec, image_options)
196
- raise "#{self.class} does not implement ready_image"
197
- end
198
-
199
- #
200
- # Destroy an image.
201
- #
202
- def destroy_image(action_handler, image_spec, image_options)
203
- raise "#{self.class} does not implement destroy_image"
204
- end
205
-
206
- #
207
- # Optional interface methods
208
- #
209
-
210
- #
211
- # Allocate a set of machines. This should have the same effect as running
212
- # allocate_machine on all machine_specs.
213
- #
214
- # Drivers do not need to implement this; the default implementation
215
- # calls acquire_machine in parallel.
216
- #
217
- # ## Parameters
218
- # action_handler - the action_handler object that is calling this method; this
219
- # is generally a driver, but could be anything that can support the
220
- # interface (i.e., in the case of the test kitchen metal driver for
221
- # acquiring and destroying VMs).
222
- # specs_and_options - a hash of machine_spec -> machine_options representing the
223
- # machines to allocate.
224
- # parallelizer - an object with a parallelize() method that works like this:
225
- #
226
- # parallelizer.parallelize(specs_and_options) do |machine_spec|
227
- # allocate_machine(action_handler, machine_spec)
228
- # end.to_a
229
- # # The to_a at the end causes you to wait until the parallelization is done
230
- #
231
- # This object is shared among other chef-metal actions, ensuring that you do
232
- # not go over parallelization limits set by the user. Use of the parallelizer
233
- # to parallelizer machines is not required.
234
- #
235
- # ## Block
236
- #
237
- # If you pass a block to this function, each machine will be yielded to you
238
- # as it completes, and then the function will return when all machines are
239
- # yielded.
240
- #
241
- # allocate_machines(action_handler, specs_and_options, parallelizer) do |machine_spec|
242
- # ...
243
- # end
244
- #
245
- def allocate_machines(action_handler, specs_and_options, parallelizer)
246
- parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
247
- allocate_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
248
- yield machine_spec if block_given?
249
- machine_spec
250
- end.to_a
251
- end
252
-
253
- # Ready machines in batch, in parallel if possible.
254
- def ready_machines(action_handler, specs_and_options, parallelizer)
255
- parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
256
- machine = ready_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
257
- yield machine if block_given?
258
- machine
259
- end.to_a
260
- end
261
-
262
- # Stop machines in batch, in parallel if possible.
263
- def stop_machines(action_handler, specs_and_options, parallelizer)
264
- parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
265
- stop_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
266
- yield machine_spec if block_given?
267
- end.to_a
268
- end
269
-
270
- # Delete machines in batch, in parallel if possible.
271
- def destroy_machines(action_handler, specs_and_options, parallelizer)
272
- parallelizer.parallelize(specs_and_options) do |machine_spec, machine_options|
273
- destroy_machine(add_prefix(machine_spec, action_handler), machine_spec, machine_options)
274
- yield machine_spec if block_given?
275
- end.to_a
276
- end
277
-
278
- protected
279
-
280
- def add_prefix(machine_spec, action_handler)
281
- AddPrefixActionHandler.new(action_handler, "[#{machine_spec.name}] ")
282
- end
283
-
284
- def get_private_key(name)
285
- Cheffish.get_private_key(name, config)
286
- end
287
- end
288
- end
1
+ require "chef/provisioning/driver"
@@ -1,70 +1 @@
1
- module ChefMetal
2
- #
3
- # Specification for a image. Sufficient information to find and contact it
4
- # after it has been set up.
5
- #
6
- class ImageSpec
7
- def initialize(image_data)
8
- @image_data = image_data
9
- end
10
-
11
- attr_reader :image_data
12
-
13
- #
14
- # Globally unique identifier for this image. Does not depend on the image's
15
- # location or existence.
16
- #
17
- def id
18
- raise "id unimplemented"
19
- end
20
-
21
- #
22
- # Name of the image. Corresponds to the name in "image 'name' do" ...
23
- #
24
- def name
25
- image_data['id']
26
- end
27
-
28
- #
29
- # Location of this image. This should be a freeform hash, with enough
30
- # information for the driver to look it up and create a image object to
31
- # access it.
32
- #
33
- # This MUST include a 'driver_url' attribute with the driver's URL in it.
34
- #
35
- # chef-metal will do its darnedest to not lose this information.
36
- #
37
- def location
38
- image_data['location']
39
- end
40
-
41
- #
42
- # Set the location for this image.
43
- #
44
- def location=(value)
45
- image_data['location'] = value
46
- end
47
-
48
- def machine_options
49
- image_data['machine_options']
50
- end
51
-
52
- def machine_options=(value)
53
- image_data['machine_options'] = value
54
- end
55
-
56
- # URL to the driver. Convenience for location['driver_url']
57
- def driver_url
58
- location ? location['driver_url'] : nil
59
- end
60
-
61
- #
62
- # Save this image_data to the server. If you have significant information that
63
- # could be lost, you should do this as quickly as possible. image_data will be
64
- # saved automatically for you after allocate_image and ready_image.
65
- #
66
- def save(action_handler)
67
- raise "save unimplemented"
68
- end
69
- end
70
- end
1
+ require "chef/provisioning/image_spec"
@@ -1,110 +1 @@
1
- module ChefMetal
2
- class Machine
3
- def initialize(machine_spec)
4
- @machine_spec = machine_spec
5
- end
6
-
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
16
-
17
- # Sets up everything necessary for convergence to happen on the machine.
18
- # The node MUST be saved as part of this procedure. Other than that,
19
- # nothing is guaranteed except that converge() will work when this is done.
20
- def setup_convergence(action_handler)
21
- raise "setup_convergence not overridden on #{self.class}"
22
- end
23
-
24
- def converge(action_handler)
25
- raise "converge not overridden on #{self.class}"
26
- end
27
-
28
- def cleanup_convergence(action_handler)
29
- raise "cleanup_convergence not overridden on #{self.class}"
30
- end
31
-
32
- def execute(action_handler, command, options = {})
33
- raise "execute not overridden on #{self.class}"
34
- end
35
-
36
- def execute_always(command, options = {})
37
- raise "execute_always not overridden on #{self.class}"
38
- end
39
-
40
- def read_file(path)
41
- raise "read_file not overridden on #{self.class}"
42
- end
43
-
44
- def download_file(action_handler, path, local_path)
45
- raise "read_file not overridden on #{self.class}"
46
- end
47
-
48
- def write_file(action_handler, path, content)
49
- raise "write_file not overridden on #{self.class}"
50
- end
51
-
52
- def upload_file(action_handler, local_path, path)
53
- raise "write_file not overridden on #{self.class}"
54
- end
55
-
56
- def create_dir(action_handler, path)
57
- raise "create_dir not overridden on #{self.class}"
58
- end
59
-
60
- # Delete file
61
- def delete_file(action_handler, path)
62
- raise "delete_file not overridden on #{self.class}"
63
- end
64
-
65
- # Return true if directory, false/nil if not
66
- def is_directory?(path)
67
- raise "is_directory? not overridden on #{self.class}"
68
- end
69
-
70
- # Return true or false depending on whether file exists
71
- def file_exists?(path)
72
- raise "file_exists? not overridden on #{self.class}"
73
- end
74
-
75
- # Return true or false depending on whether remote file differs from local path or content
76
- def files_different?(path, local_path, content=nil)
77
- raise "file_different? not overridden on #{self.class}"
78
- end
79
-
80
- # Set file attributes { mode, :owner, :group }
81
- def set_attributes(action_handler, path, attributes)
82
- raise "set_attributes not overridden on #{self.class}"
83
- end
84
-
85
- # Get file attributes { :mode, :owner, :group }
86
- def get_attributes(path)
87
- raise "get_attributes not overridden on #{self.class}"
88
- end
89
-
90
- # Ensure the given URL can be reached by the remote side (possibly by port forwarding)
91
- # Must return the URL that the remote side can use to reach the local_url
92
- def make_url_available_to_remote(local_url)
93
- raise "make_url_available_to_remote not overridden on #{self.class}"
94
- end
95
-
96
- def disconnect
97
- raise "disconnect not overridden on #{self.class}"
98
- end
99
-
100
- # TODO get rid of the action_handler attribute, that is ridiculous
101
- # Detect the OS on the machine (assumes the machine is up)
102
- # Returns a triplet:
103
- # platform, platform_version, machine_architecture = machine.detect_os(action_handler)
104
- # This triplet is suitable for passing to the Chef metadata API:
105
- # https://www.opscode.com/chef/metadata?p=#{platform}&pv=#{platform_version}&m=#{machine_architecture}
106
- def detect_os(action_handler)
107
- raise "detect_os not overridden on #{self.class}"
108
- end
109
- end
110
- end
1
+ require "chef/provisioning/machine"