chef-metal 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75907d8e5aa3714df11b2d37090fb42babe16499
4
- data.tar.gz: 61cadff437fe83b341b74da8d41d9d0164c670c7
3
+ metadata.gz: af79447510d93b295a7d77a3223d670bdc569415
4
+ data.tar.gz: ac28faf8d8afa3026960b9997de94d9c4fc77369
5
5
  SHA512:
6
- metadata.gz: 6b46ef77e100475dd856861eb9db77202919dd28150b7606b9deddd8658c7594c2922755aaae0b2c9af71f71905f8b33b9a31dcb15e79dc9fffaba338d5981a2
7
- data.tar.gz: 4fd6d879cb7d174f5ef65b7af723f4079e017f04975f42e4c6f9346e2888485aec7b3b3b70a1ca56d74e6678ee0a3b6483c54ef05f5b3c80c57ffb4f6d76bbde
6
+ metadata.gz: 49762ba3a7f0f71677b85d6f9657cdb05174c1d389ba96825bb218f9af7dd557f35ab515dd391865caba7dc20a6a3ddfbd12b1a3c566219bab1e6cda7d8248fa
7
+ data.tar.gz: 5412dfb1f503aa30259bf37c16a7f8e46dffc98c7434375fefaf208a3745af25208052d60a4982a6a809444eaaeb82211e6490fa5a9c52cced6a7347cf70c0a0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Chef Metal Changelog
2
2
 
3
+ ## 0.10.2 (5/2/2014)
4
+
5
+ - Fix crash with add_provisioner_options when provisioner_options is not yet set
6
+
3
7
  ## 0.10.1 (5/2/2014)
4
8
 
5
9
  - Fix a crash when uploading files in a machine batch
@@ -9,7 +9,11 @@ module ChefMetal
9
9
  with :machine_batch
10
10
 
11
11
  def add_provisioner_options(options, &block)
12
- with_provisioner_options(Chef::Mixin::DeepMerge.hash_only_merge(current_provisioner_options, options), &block)
12
+ if current_provisioner_options
13
+ with_provisioner_options(Chef::Mixin::DeepMerge.hash_only_merge(current_provisioner_options, options), &block)
14
+ else
15
+ with_provisioner_options(options)
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -0,0 +1,81 @@
1
+ require 'cheffish'
2
+ require 'cheffish/cheffish_server_api'
3
+
4
+ module ChefMetal
5
+ #
6
+ # Specification for a machine. Sufficient information to find and contact it
7
+ # after it has been set up.
8
+ #
9
+ class MachineSpec
10
+ def initialize(node, chef_server)
11
+ @node = node
12
+ @chef_server = chef_server
13
+ end
14
+
15
+ def self.get(name, chef_server)
16
+ rest = Cheffish::CheffishServerAPI.new(chef_server || Cheffish.current_chef_server)
17
+ MachineSpec.new(rest.get("/nodes/#{name}"), chef_server)
18
+ end
19
+
20
+ #
21
+ # Globally unique identifier for this machine. Does not depend on the machine's
22
+ # location or existence.
23
+ #
24
+ def id
25
+ "#{@chef_server[:chef_server_url]}/nodes/#{name}"
26
+ end
27
+
28
+ #
29
+ # Name of the machine. Corresponds to the name in "machine 'name' do" ...
30
+ #
31
+ def name
32
+ @node['name']
33
+ end
34
+
35
+ #
36
+ # Location of this machine. This should be a freeform hash, with enough
37
+ # information for the provider to look it up and create a Machine object to
38
+ # access it.
39
+ #
40
+ # This MUST include a 'provider_url' attribute with the provider's URL in it.
41
+ #
42
+ # chef-metal will do its darnedest to not lose this information.
43
+ #
44
+ def location
45
+ metal_attr('location')
46
+ end
47
+
48
+ #
49
+ # Set the location for this machine.
50
+ #
51
+ def location=(value)
52
+ @node['normal']['metal'] ||= {}
53
+ @node['normal']['metal']['spec'] = value
54
+ end
55
+
56
+ #
57
+ # Save this node to the server. If you have significant information that
58
+ # could be lost, you should do this as quickly as possible. Data will be
59
+ # saved automatically for you after allocate_machine and ready_machine.
60
+ #
61
+ def save(action_handler)
62
+ # Save the node to the server.
63
+ ChefMetal.inline_resource(action_handler) do
64
+ chef_node node['name'] do
65
+ chef_server @chef_server
66
+ raw_json node
67
+ end
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def metal_attr(attr)
74
+ if @node['normal'] && @node['normal']['metal']
75
+ @node['normal']['metal'][attr]
76
+ else
77
+ nil
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,239 @@
1
+ module ChefMetal
2
+ #
3
+ # A Provider 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 Provider instance corresponds to a single account.
7
+ # For Vagrant, it is a directory where VM files are found.
8
+ #
9
+ # == How to Make a Provider
10
+ #
11
+ # To implement a Provider, 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 provider.
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
+ # - delete_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
+ # - resource_created - a hook to tell you when a resource associated with your
26
+ # provider has been created.
27
+ #
28
+ # Additionally, you must create a file named `chef_metal/provider_init/<scheme>.rb`,
29
+ # where <scheme> is the name of the scheme you chose for your driver_url. This
30
+ # file, when required, must call
31
+ #
32
+ # All of these methods must be idempotent - if the work is already done, they
33
+ # just don't do anything.
34
+ #
35
+ class Provider
36
+ #
37
+ # Inflate a driver from node information; we don't want to force the
38
+ # driver to figure out what the driver really needs, since it varies
39
+ # from driver to driver.
40
+ #
41
+ # ## Parameters
42
+ # driver_url - the URL to inflate the driver
43
+ #
44
+ # ## Returns
45
+ # A Provider representing the given driver_url.
46
+ def initialize(driver_url)
47
+ # We do not save it ... it's up to the driver to extract whatever information
48
+ # it wants.
49
+ end
50
+
51
+ #
52
+ # A URL representing the driver and the place where machines come from.
53
+ # This will be stuffed in attributes in the node so that the node can be
54
+ # reinflated. URLs must have a unique scheme identifying the driver
55
+ # class, and enough information to identify the place where created machines
56
+ # can be found. For AWS, this is the account number; for lxc and vagrant,
57
+ # it is the directory in which VMs and containers are.
58
+ #
59
+ # For example:
60
+ # - fog:AWS:123456789012
61
+ # - vagrant:/var/vms
62
+ # - lxc:
63
+ # - docker:
64
+ #
65
+ def driver_url
66
+ raise "#{self.class} does not implement driver_url"
67
+ end
68
+
69
+ #
70
+ # Allocate a machine from the PXE/cloud/VM/container provider. This method
71
+ # does not need to wait for the machine to boot or have an IP, but it must
72
+ # store enough information in node['normal']['driver_output'] to find
73
+ # the machine later in ready_machine.
74
+ #
75
+ # If a machine is powered off or otherwise unusable, this method may start
76
+ # it, but does not need to wait until it is started. The idea is to get the
77
+ # gears moving, but the job doesn't need to be done :)
78
+ #
79
+ # ## Parameters
80
+ # action_handler - the action_handler object that is calling this method; this
81
+ # is generally a provider, but could be anything that can support the
82
+ # interface (i.e., in the case of the test kitchen metal driver for
83
+ # acquiring and destroying VMs).
84
+ #
85
+ # existing_machine - a MachineSpec representing the existing machine (if any).
86
+ #
87
+ # machine_options - a set of options representing the desired provisioning
88
+ # state of the machine (image name, bootstrap ssh credentials,
89
+ # etc.). This will NOT be stored in the node, and is
90
+ # ephemeral.
91
+ #
92
+ # ## Returns
93
+ #
94
+ # Modifies the passed-in machine_spec. Anything in here will be saved
95
+ # back to the node.
96
+ #
97
+ def allocate_machine(action_handler, machine_spec, machine_options)
98
+ raise "#{self.class} does not implement allocate_machine"
99
+ end
100
+
101
+ #
102
+ # Ready a machine, to the point where it is running and accessible via a
103
+ # transport. This will NOT allocate a machine, but may kick it if it is down.
104
+ # This method waits for the machine to be usable, returning a Machine object
105
+ # pointing at the machine, allowing useful actions like setup, converge,
106
+ # execute, file and directory.
107
+ #
108
+ # ## Parameters
109
+ # action_handler - the action_handler object that is calling this method; this
110
+ # is generally a provider, but could be anything that can support the
111
+ # interface (i.e., in the case of the test kitchen metal driver for
112
+ # acquiring and destroying VMs).
113
+ # machine_spec - MachineSpec representing this machine.
114
+ #
115
+ # ## Returns
116
+ #
117
+ # Machine object pointing at the machine, allowing useful actions like setup,
118
+ # converge, execute, file and directory.
119
+ #
120
+ def ready_machine(action_handler, machine_spec)
121
+ raise "#{self.class} does not implement ready_machine"
122
+ end
123
+
124
+ #
125
+ # Connect to a machine without allocating or readying it. This method will
126
+ # NOT make any changes to anything, or attempt to wait.
127
+ #
128
+ # ## Parameters
129
+ # machine_spec - MachineSpec representing this machine.
130
+ #
131
+ # ## Returns
132
+ #
133
+ # Machine object pointing at the machine, allowing useful actions like setup,
134
+ # converge, execute, file and directory.
135
+ #
136
+ def connect_to_machine(machine_spec)
137
+ raise "#{self.class} does not implement connect_to_machine"
138
+ end
139
+
140
+ #
141
+ # Delete the given machine (idempotent). Should destroy the machine,
142
+ # returning things to the state before allocate_machine was called.
143
+ #
144
+ def delete_machine(action_handler, machine_spec)
145
+ raise "#{self.class} does not implement delete_machine"
146
+ end
147
+
148
+ #
149
+ # Stop the given machine.
150
+ #
151
+ def stop_machine(action_handler, machine_spec)
152
+ raise "#{self.class} does not implement stop_machine"
153
+ end
154
+
155
+ #
156
+ # Optional interface methods
157
+ #
158
+
159
+ #
160
+ # Allocate a set of machines. This should have the same effect as running
161
+ # allocate_machine on all nodes.
162
+ #
163
+ # Providers do not need to implement this; the default implementation
164
+ # calls acquire_machine in parallel.
165
+ #
166
+ # ## Parameter
167
+ # action_handler - the action_handler object that is calling this method; this
168
+ # is generally a provider, but could be anything that can support the
169
+ # interface (i.e., in the case of the test kitchen metal driver for
170
+ # acquiring and destroying VMs).
171
+ # nodes - a list of nodes representing the nodes to acquire.
172
+ # parallelizer - an object with a parallelize() method that works like this:
173
+ #
174
+ # parallelizer.parallelize(nodes) do |node|
175
+ # allocate_machine(action_handler, node)
176
+ # end.to_a
177
+ # # The to_a at the end causes you to wait until the parallelization is done
178
+ #
179
+ # This object is shared among other chef-metal actions, ensuring that you do
180
+ # not go over parallelization limits set by the user. Use of the parallelizer
181
+ # to parallelizer machines is not required.
182
+ #
183
+ def allocate_machines(action_handler, machine_specs, parallelizer)
184
+ parallelizer.parallelize(machine_specs) do |machine_spec|
185
+ allocate_machine(add_prefix(machine_spec, action_handler), machine_spec)
186
+ yield machine_spec if block_given?
187
+ machine
188
+ end.to_a
189
+ end
190
+
191
+ # Acquire machines in batch, in parallel if possible.
192
+ def acquire_machines(action_handler, machine_specs, parallelizer)
193
+ parallelizer.parallelize(machine_specs) do |machine_spec|
194
+ machine = acquire_machine(add_prefix(machine_spec, action_handler), machine_spec)
195
+ yield machine_spec, machine if block_given?
196
+ machine
197
+ end.to_a
198
+ end
199
+
200
+ # Stop machines in batch, in parallel if possible.
201
+ def stop_machines(action_handler, nodes_json, parallelizer)
202
+ parallelizer.parallelize(machine_specs) do |machine_spec|
203
+ stop_machine(add_prefix(machine_spec, action_handler), machine_spec)
204
+ yield machine_spec if block_given?
205
+ end.to_a
206
+ end
207
+
208
+ # Delete machines in batch, in parallel if possible.
209
+ def delete_machines(action_handler, machine_specs, parallelizer)
210
+ parallelizer.parallelize(machine_specs) do |machine_spec|
211
+ delete_machine(add_prefix(machine_spec, action_handler), machine_spec)
212
+ yield machine_spec if block_given?
213
+ end.to_a
214
+ end
215
+
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
+ protected
224
+
225
+ def save_node(provider, node, chef_server)
226
+ # Save the node and create the client. TODO strip automatic attributes first so we don't race with "current state"
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']}] ")
237
+ end
238
+ end
239
+ end
@@ -1,3 +1,3 @@
1
1
  module ChefMetal
2
- VERSION = '0.10.1'
2
+ VERSION = '0.10.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-metal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
@@ -172,7 +172,9 @@ files:
172
172
  - lib/chef_metal/machine/unix_machine.rb
173
173
  - lib/chef_metal/machine/windows_machine.rb
174
174
  - lib/chef_metal/machine.rb
175
+ - lib/chef_metal/machine_spec.rb
175
176
  - lib/chef_metal/openstack_credentials.rb
177
+ - lib/chef_metal/provider.rb
176
178
  - lib/chef_metal/provider_action_handler.rb
177
179
  - lib/chef_metal/provisioner.rb
178
180
  - lib/chef_metal/recipe_dsl.rb