chef-metal 0.10.1 → 0.10.2
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 +4 -0
- data/lib/chef_metal/chef_run_data.rb +5 -1
- data/lib/chef_metal/machine_spec.rb +81 -0
- data/lib/chef_metal/provider.rb +239 -0
- data/lib/chef_metal/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af79447510d93b295a7d77a3223d670bdc569415
|
4
|
+
data.tar.gz: ac28faf8d8afa3026960b9997de94d9c4fc77369
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49762ba3a7f0f71677b85d6f9657cdb05174c1d389ba96825bb218f9af7dd557f35ab515dd391865caba7dc20a6a3ddfbd12b1a3c566219bab1e6cda7d8248fa
|
7
|
+
data.tar.gz: 5412dfb1f503aa30259bf37c16a7f8e46dffc98c7434375fefaf208a3745af25208052d60a4982a6a809444eaaeb82211e6490fa5a9c52cced6a7347cf70c0a0
|
data/CHANGELOG.md
CHANGED
@@ -9,7 +9,11 @@ module ChefMetal
|
|
9
9
|
with :machine_batch
|
10
10
|
|
11
11
|
def add_provisioner_options(options, &block)
|
12
|
-
|
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
|
data/lib/chef_metal/version.rb
CHANGED
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.
|
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
|