chef-metal 0.14.2 → 0.15

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