clc-fork-chef-metal 0.11.beta.6 → 0.11.2.alpha.1

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: ef0925df69f5f0d7cf6f51b0b849f155d4c2b6ee
4
- data.tar.gz: dfc2e5acb07a424fac4d9041dff233c631aaf111
3
+ metadata.gz: 4aeb6b366bba61cd66941ffbf1159d6a9c8f5e35
4
+ data.tar.gz: ace414410903b2f164c3699bfb938cf4a9e76292
5
5
  SHA512:
6
- metadata.gz: cbbc0262f139ba2883711e183cb192f895b3accd2389c56a8b68619b21c85fcbcecbd6cbf134b1b45352729334f6bc5e7a34ff759430fc1eadf6e8fe81dfcd04
7
- data.tar.gz: 7b3e07b27e49b7962d1f20a7ef6e7823d70d78b5606022fcac731f53a1c8f6808f9b017a975ed4bd811cfe70fabda92f423b7158aa67099bb0da2f3f3332d2bf
6
+ metadata.gz: db58b28f165074f0100c5a8db05180e1f28f22fce8868551f295b7f3bef49cc5c44b6c7ec6b3d175517a44b9f5bd6750a0bf7695768e5d12a88baccad6e3ee11
7
+ data.tar.gz: 3fee03a117fb4ee67076be5c234213d8701d85eccbe5ce615b1c0f6486f316b7edae8d600af427da1e0daa1615c2c5f50a778aef2a67e231643159168bb7851a
data/CHANGELOG.md CHANGED
@@ -1,9 +1,24 @@
1
1
  # Chef Metal Changelog
2
2
 
3
- ## 0.11.beta.6 (5/28/2014)
3
+ ## 0.11.2 (6/4/2014)
4
4
 
5
- - Fix machine_batch defaults to be significantly less stupid
6
- - Remove with_machine_batch
5
+ - Fix issue where machines with different drivers could get default options from the global current driver
6
+
7
+ ## 0.11.1 (6/4/2014)
8
+
9
+ - fix local mode port forwarding on IPv6 hosts
10
+
11
+ ## 0.11 (6/4/2014)
12
+
13
+ - New Driver interface (see docs/ and blogs/ directories for documentation)
14
+ - New configuration (see docs/ and blogs/)
15
+ - get rid of annoying SSL warning (note: this turns off SSL verification, which was the default anyway)
16
+ - fix machine_batch error report to be less verbose
17
+ - fail when machine is being moved from driver to driver
18
+ - @marcusn disconnect from SSH when there is a problem
19
+ - fix SSH gateway code to honor any options given (@marcusn)
20
+ - Make machine_batch auto batching smarter (only batch things that have the same actions)
21
+ - Allow auto batching to be turned off with `auto_batch_machines = false` in recipes or config
7
22
  - Allow this:
8
23
  ```ruby
9
24
  machine_batch do
@@ -17,20 +32,8 @@
17
32
  machines 'a', 'b', 'c'
18
33
  action :destroy
19
34
  end
20
- - fix SSH gateway code to honor any options given (@marcusn)
21
-
22
- ## 0.11.beta.5 (5/28/2014)
23
-
24
35
  - fix issue setting Hosted Chef ACLs on nodes
25
- - fix single-machine converge crash
26
-
27
- ## 0.11.beta.2 (5/27/2014)
28
-
29
- - Bring in cheffish-0.5.beta.2
30
-
31
- ## 0.11.beta (5/23/2014)
32
-
33
- - New Driver interface (see docs/ and blogs/ directories for documentation)
36
+ - fix local mode forwarding in mixed IPv4/IPv6 environments
34
37
 
35
38
  ## 0.10.2 (5/2/2014)
36
39
 
data/README.md CHANGED
@@ -3,31 +3,72 @@ Chef Metal
3
3
 
4
4
  This library solves the problem of repeatably creating machines and infrastructures in Chef. It has a plugin model that lets you write bootstrappers for your favorite infrastructures, including VirtualBox, EC2, LXC, bare metal, and many more!
5
5
 
6
- Currently, chef-metal supports vagrant, Unixes/ssh, and Windows/winrm with real chef-servers or with automagical chef-zero tunneling. Fog and Docker support (to cover EC2 and LXC) are next up. Further out, we'd like to extend support to image factories (using the machine resource to produce images) and PXE support.
6
+ [This video](https://www.youtube.com/watch?v=Yb8QdL30WgM) explains the basics of chef-metal (though provisioners are now called drivers). Slides (more up to date) are [here](http://slides.com/jkeiser/chef-metal).
7
+
8
+ Date | Blog
9
+ -----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------
10
+ 6/3/2014 | [machine_batch and parallelization](https://github.com/opscode/chef-metal/blob/master/docs/blogs/2012-05-28-machine_batch.html.markdown#chef-metal-parallelization)
11
+ 6/3/2014 | [Chef Metal, Configuration and Drivers](https://github.com/opscode/chef-metal/blob/master/docs/blogs/2012-05-22-new-driver-interface.html.markdown#chef-metal-configuration-and-drivers)
12
+ 3/4/2014 | [Chef Metal 0.2: Overview](http://www.getchef.com/blog/2014/03/04/chef-metal-0-2-release/) - this is a pretty good overview (though dated).
13
+ 12/20/2014 | [Chef Metal Alpha](http://www.getchef.com/blog/2013/12/20/chef-metal-alpha/)
7
14
 
8
15
  Try It Out
9
16
  ----------
10
17
 
11
- To give it a spin, get chef 11.8 or greater try this:
18
+ You can try out Metal in many different flavors.
19
+
20
+ HINT: chef-metal looks prettiest with chef 11.14 alpha. `gem install chef --pre` to get it.
12
21
 
13
- git clone https://github.com/opscode/cheffish.git
14
- cd cheffish
15
- rake install
16
- cd ..
22
+ ### Vagrant
17
23
 
18
- git clone https://github.com/opscode/chef-metal.git
19
- cd chef-metal
20
- rake install
21
-
22
- cd chef-metal
23
- chef-client -z -o myapp::vagrant,myapp::linux,myapp::small
24
+ To give it a spin, install Vagrant and VirtualBox and try this from the `chef-metal/docs/examples` directory:
25
+
26
+ ```
27
+ gem install chef-metal
28
+ export CHEF_DRIVER=vagrant
29
+ chef-client -z vagrant_linux.rb simple.rb
30
+ ```
24
31
 
25
32
  This will create two vagrant precise64 linux boxes, "mario" and "luigi1", in `~/machinetest`, bootstrapped to an empty runlist. For Windows, you can replace `myapp::linux` with `myapp::windows`, but you'll need your own Windows vagrant box to do that (licensing!).
26
33
 
34
+ ### AWS
35
+
36
+ If you have an AWS account, you can spin up a machine there like this:
37
+
38
+ ```
39
+ gem install chef-metal
40
+ export CHEF_DRIVER=fog:AWS
41
+ chef-client -z simple.rb
42
+ ```
43
+
44
+ This will create two linux boxes in the AWS account referenced by your default profile in `~/.aws/config` (or your environment variables).
45
+
46
+ ### DigitalOcean
47
+
48
+ If you are on DigitalOcean and using the `tugboat` gem, you can do this:
49
+
50
+ ```
51
+ gem install chef-metal
52
+ export CHEF_DRIVER=fog:DigitalOcean
53
+ chef-client -z simple.rb
54
+ ```
55
+
56
+ If you aren't using the `tugboat` gem, you can put `driver` and `driver_options` into your `.chef/knife.rb` file.
57
+
58
+ This will use your tugboat settings to create whatever sort of instance you normally create.
59
+
60
+ ### Cleaning up
61
+
62
+ When you are done with the examples, run this to clean up:
63
+
64
+ ```
65
+ chef-client -z destroy_all.rb
66
+ ```
67
+
27
68
  What Is Chef Metal?
28
69
  -------------------
29
70
 
30
- Chef Metal has two major abstractions: the machine resource, and provisioners.
71
+ Chef Metal has two major abstractions: the machine resource, anf drivers.
31
72
 
32
73
  ### The `machine` resource
33
74
 
@@ -54,148 +95,143 @@ end
54
95
 
55
96
  You will notice the dynamic nature of the number of web servers. It's all code, your imagination is the limit :)
56
97
 
57
- Kitchen
58
- -------
59
-
60
- Chef Metal also works with Test Kitchen, allowing you to test entire clusters, not just machines! The repository for the kitchen-metal gem is https://github.com/doubt72/kitchen-metal.
61
-
62
- Provisioners
63
- ------------
98
+ ### Drivers
64
99
 
65
- Provisioners handle the real work of getting those abstract definitions into real, physical form. They handle the following tasks, idempotently (you can run the resource again and again and it will only create the machine once--though it may notice things are wrong and fix them!):
100
+ Drivers handle the real work of getting those abstract definitions into real, physical form. They handle the following tasks, idempotently (you can run the resource again and again and it will only create the machine once--though it may notice things are wrong and fix them!):
66
101
 
67
102
  * Acquiring machines from the cloud, creating containers or VMs, or grabbing bare metal
68
103
  * Connecting to those machines via ssh, winrm, or other transports
69
104
  * Bootstrapping chef onto the machines and converging the recipes you suggested
70
105
 
71
- The provisioner API is separated out so that new provisioners can be made with minimal effort (without having to rewrite ssh, tunneling, bootstrapping, and OS support). But to the user, they appear as a single thing, so that the machine acquisition can use its smarts to autodetect the other bits (transports, OS's, etc.).
106
+ The driver API is separated out so that new drivers can be made with minimal effort (without having to rewrite ssh, tunneling, bootstrapping, and OS support). But to the user, they appear as a single thing, so that the machine acquisition can use its smarts to autodetect the other bits (transports, OS's, etc.).
72
107
 
73
- Provisioners save their data in the Chef node itself, so that they will be accessible to everyone who is using the Chef server to manage the nodes.
108
+ Drivers save their data in the Chef node itself, so that they will be accessible to everyone who is using the Chef server to manage the nodes.
74
109
 
75
- Provisioners each have their own repository. Current provisioners:
110
+ Drivers each have their own repository. Current drivers:
76
111
 
77
112
  **Cloud:**
78
113
  - [FOG: EC2, DigitalOcean, OpenStack, etc.](https://github.com/opscode/chef-metal-fog)
79
114
 
80
115
  **Virtualization:**
81
116
  - [Vagrant: VirtualBox, VMWare Fusion, etc.](https://github.com/opscode/chef-metal-vagrant)
117
+ - [VSphere](https://github.com/RallySoftware-cookbooks/chef-metal-vsphere) (not yet up to date with 0.11)
82
118
 
83
119
  **Containers:**
84
- - [LXC](https://github.com/opscode/chef-metal-lxc)
85
- - [Docker](https://github.com/opscode/chef-metal-docker)
120
+ - [LXC](https://github.com/opscode/chef-metal-lxc) (not yet up to date with 0.11)
121
+ - [Docker](https://github.com/opscode/chef-metal-docker) (not yet up to date with 0.11)
86
122
 
87
123
  **Bare Metal:**
88
- - [SSH (no PXE)](https://github.com/double-z/chef-metal-ssh)
89
-
90
- ### Vagrant
124
+ - [SSH (no PXE)](https://github.com/double-z/chef-metal-ssh) (not yet up to date with 0.11)
91
125
 
92
- chef-zero comes with a provisioner for Vagrant, an abstraction that covers VirtualBox, VMWare and other Virtual Machine drivers. To run it, you can check out the sample recipes with:
126
+ ### Anatomy of a Recipe
93
127
 
94
- ```
95
- chef-client -z -o myapp::vagrant,myapp::linux,myapp::small
96
- ```
97
-
98
- The provisioner specification is in myapp::vagrant and myapp::linux [sample recipes](https://github.com/opscode/chef-metal/tree/master/cookbooks/myapp/recipes), copy/pasted here for your convenience:
128
+ chef-zero comes with a provisioner for Vagrant, an abstraction that covers VirtualBox, VMWare and other Virtual Machine drivers. In docs/examples, you can run this to try it:
99
129
 
100
130
  ```ruby
101
- vagrant_cluster "#{ENV['HOME']}/machinetest"
102
-
103
- directory "#{ENV['HOME']}/machinetest/repo"
104
- with_chef_local_server :chef_repo_path => "#{ENV['HOME']}/machinetest/repo"
105
-
106
- vagrant_box 'precise64' do
107
- url 'http://files.vagrantup.com/precise32.box'
108
- end
131
+ export CHEF_DRIVER=vagrant
132
+ chef-client -z vagrant_linux.rb simple.rb
109
133
  ```
110
134
 
111
- `vagrant_cluster` declares a directory where all the vagrant definitions will be stored, and uses `with_provisioner` internally to tell Chef Metal that this is the provisioner we want to use for machines.
135
+ This is a chef-client run, which runs multiple **recipes.** Chef Metal is nothing but resources you put in recipes.
112
136
 
113
- `vagrant_box` makes sure a particular vagrant box exists, and lets you specify `provisioner_options` for things like port forwarding, OS definitions, and any other vagrant-isms. A more complicated vagrant box, with provisioner options, can be found in [myapp::windows](https://github.com/opscode/chef-metal/blob/master/cookbooks/myapp/recipes/windows.rb).
137
+ The driver is specified on the command line. Drivers are URLs. You could use `vagrant:~/vms` or `fog:AWS:default:us-east-1' as driver URLs. More information [here.](https://github.com/opscode/chef-metal/blob/master/docs/configuration.md#setting-the-driver-with-a-driver-url)
114
138
 
115
- `with_chef_local_server` is a generic directive that creates a chef-zero server pointed at the given repository. nodes, clients, data bags, and all data will be stored here on your provisioner machine if you do this. You can use `with_chef_server` instead if you want to point at OSS, Hosted or Enterprise Chef, and if you don't specify a Chef server at all, it will use the one you are running chef-client against. Keep in mind when using `with_chef_server` and running `chef-client -z` on your workstation that you will also need to set the client name and signing key for the chef server. If you've already got knife.rb set up, then something like this will correctly create a client for the chef server on instance using your knife.rb configuration:
139
+ The `vagrant_linux.rb` recipe handles the physical specification of the machines and Vagrant box:
116
140
 
117
141
  ```ruby
118
- require 'chef/config'
142
+ require 'chef_metal_vagrant'
119
143
 
120
- with_chef_server "https://chef-server.example.org", {
121
- :client_name => Chef::Config[:node_name],
122
- :signing_key_filename => Chef::Config[:client_key]
144
+ vagrant_box 'precise64' do
145
+ url 'http://files.vagrantup.com/precise64.box'
146
+ end
147
+
148
+ with_machine_options :vagrant_options => {
149
+ 'vm.box' => 'precise64'
123
150
  }
124
151
  ```
125
152
 
126
- Typically, you declare these in separate files from your machine resources. Chef Metal picks up the provisioners you have declared, and uses them to instantiate the machines you request. The actual machine definitions, in this case, are in `myapp::small`, and are generic--you could use them against EC2 as well:
153
+ `require 'chef_metal_vagrant'` is how we bring in the `vagrant_box` resource.
127
154
 
128
- ```ruby
129
- machine 'mario' do
130
- recipe 'postgresql'
131
- recipe 'mydb'
132
- tag 'mydb_master'
133
- end
155
+ `vagrant_box` makes sure a particular vagrant box exists, and lets you specify `machine_options` for things like port forwarding, OS definitions, and any other vagrant-isms.
134
156
 
135
- num_webservers = 1
157
+ Typically, you declare these in separate files from your machine resources. Chef Metal picks up the drivers and machine_options you have declared, and uses them to instantiate the machines you request. The actual machine definitions, in this case, are in `simple.rb`, and are generic--you could use them against Azure or EC2 as well:
136
158
 
137
- 1.upto(num_webservers) do |i|
138
- machine "luigi#{i}" do
139
- recipe 'apache'
140
- recipe 'mywebapp'
141
- end
159
+ ```ruby
160
+ machine 'mario' do
161
+ tag 'itsame'
142
162
  end
143
163
  ```
144
164
 
145
- ### Fog (EC2 and friends)
165
+ Other directives, like `recipe 'apache'`, help you set run lists and other information about the machine.
166
+
167
+ ### Fog (EC2, Openstack and friends)
146
168
 
147
- chef-metal also comes with a [Fog](http://fog.io/) provisioner that handles provisioning to Amazon's EC2 and other cloud drivers. (Only EC2 has been tested so far.) Before you begin, you will need to put your AWS credentials in ~/.aws/config in the format [mentioned in Option 1 here](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#d0e726).
169
+ chef-metal also comes with a [Fog](http://fog.io/) provisioner that handles provisioning to Openstack, Rackspace, Amazon's EC2 and other cloud drivers. Before you begin, you will need to put your AWS credentials in ~/.aws/config in the format [mentioned in Option 1 here](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#d0e726). There are other ways to specify your credentials, but this is the standard one for the Amazon CLI.
148
170
 
149
171
  Once your credentials are in, basic usage looks like this:
150
172
 
151
173
  ```
152
- chef-client -z -o myapp::ec2,myapp::small
174
+ export CHEF_DRIVER=fog:AWS
175
+ chef-client -z simple.rb
153
176
  ```
154
177
 
155
- The provisioner definition in `myapp::ec2` looks like this:
178
+ Other valid URLs include `fog:AWS:myprofilename` and `fog:AWS:profilename:us-west-2`.
156
179
 
157
- ```ruby
158
- ec2testdir = File.expand_path('~/ec2test')
180
+ Most Chef Metal drivers try hard to provide reasonable defaults so you can get started easily. Once you have specified your credentials, AMIs and other things are chosen for you.
159
181
 
160
- directory ec2testdir
182
+ You will usually want to create or input a custom key pair for bootstrap. To customize, specify keys and AMI and other options, you can make recipes like this:
161
183
 
162
- with_fog_ec2_provisioner # :driver => 'AWS'
184
+ ```ruby
185
+ require 'chef_metal_fog'
163
186
 
164
- with_provisioner_options :image_id => 'ami-5ee70037'
187
+ fog_key_pair 'my_bootstrap_key'
165
188
 
166
- fog_key_pair 'me' do
167
- private_key_path "#{ec2testdir}/me"
168
- public_key_path "#{ec2testdir}/me.pub"
169
- end
189
+ with_machine_options :bootstrap_options => {
190
+ :key_name => 'my_bootstrap_key',
191
+ :image_id => 'ami-59a4a230',
192
+ :flavor_id => 't1.micro'
193
+ }
170
194
  ```
171
195
 
172
- `with_fog_ec2_provisioner` tells chef-metal to use the Fog provisioner against EC2. If you specify your credentials in `~/.aws/config`, you don't *have* to specify anything else; it will use the Fog defaults. You may pass a hash of parameters to `with_fog_ec2_provisioner` that is described [here](https://github.com/opscode/chef-metal/blob/master/lib/chef_metal/provisioner/fog_provisioner.rb#L21-L32).
196
+ `fog_key_pair` creates a new key pair (if the files do not already exist) and uploads it to AWS (it will toss an error if the key pair already exists and does not match). By default, `fog_key_pair` will look for matching key files in .chef/keys, ~/.chef/keys and ~/.ssh. If it does not find one, it will place the key in `.chef/keys`. You can override this path in fog_key_pair, but if you do, you will want to modify `private_key_paths` in your configuration to match.
197
+
198
+ `with_machine_options` specifies machine_options that will be applied to any `machine` resources chef-client encounters.
199
+
200
+ You will notice that we are still using `simple.rb` here. Machine definitions are generally driver-independent. This is an important feature that allows you to spin up your clusters in different places to create staging, test or miniature dev environments.
173
201
 
174
- `fog_key_pair` creates a new key pair (if the files do not already exist) and automatically tells the Provisioner to use it to bootstrap subsequent machines. The private/public key pair will be automatically authorized to log on to the instance on first boot.
202
+ ### Pointing Boxes at Chef Servers
175
203
 
176
- To pass options like ami, you can say something like this:
204
+ By default, Chef Metal will put your boxes on the same Chef server you started chef-client with (in the case of -z, that's a local chef-zero server). Sometimes you want to put your boxes on different servers. There are a couple of ways to do that:
177
205
 
178
206
  ```ruby
179
- with_provisioner_options :image_id => 'ami-5ee70037'
207
+ with_chef_local_server :chef_repo_path => '~/repo'
180
208
  ```
181
209
 
182
- If you need to pass bootstrapping options on a per-machine basis, you can do that as well by doing something like the following:
210
+ `with_chef_local_server` is a generic directive that creates a chef-zero server pointed at the given repository. nodes, clients, data bags, and all data will be stored here on your provisioner machine if you do this.
211
+
212
+ You can use `with_chef_server` instead if you want to point at OSS, Hosted or Enterprise Chef, and if you don't specify a Chef server at all, it will use the one you are running chef-client against. Keep in mind when using `with_chef_server` and running `chef-client -z` on your workstation that you will also need to set the client name and signing key for the chef server. If you've already got knife.rb set up, then something like this will correctly create a client for the chef server on instance using your knife.rb configuration:
183
213
 
184
214
  ```ruby
185
- machine "Ubuntu_64bit" do
186
- action :create
187
- provisioner_options 'bootstrap_options' => {
188
- 'image_id' => 'ami-59a4a230',
189
- 'flavor_id' => 't1.micro'
190
- }
191
- end
215
+ with_chef_server "https://chef-server.example.org",
216
+ :client_name => Chef::Config[:node_name],
217
+ :signing_key_filename => Chef::Config[:client_key]
192
218
  ```
193
219
 
194
- You will notice that we are still using `myapp::small` here. Machine definitions are generally provisioner-independent. This is an important feature that allows you to spin up your clusters in different places to create staging, test or miniature dev environments.
220
+ Kitchen
221
+ -------
222
+
223
+ Chef Metal also works with Test Kitchen, allowing you to test entire clusters, not just machines! The repository for the kitchen-metal gem is https://github.com/doubt72/kitchen-metal.
224
+
225
+ Documentation
226
+ -------------
227
+ * [Configuration](https://github.com/opscode/chef-metal/blob/master/docs/configuration.md#configuring-and-using-metal-drivers)
228
+ * [Writing Drivers](https://github.com/opscode/chef-metal/blob/master/docs/building_drivers.md#writing-drivers)
229
+ * [Embedding](https://github.com/opscode/chef-metal/blob/master/docs/embedding.md)
195
230
 
196
231
  Bugs and The Plan
197
232
  -----------------
198
233
 
199
- It's early days. *Please* submit bugs at https://github.com/opscode/chef-metal/issues, contact jkeiser on Twitter at @jkeiser2, email at jkeiser@opscode.com
234
+ Please submit bugs, gripes and feature requests at [https://github.com/opscode/chef-metal/issues](https://twitter.com/jkeiser2), contact jkeiser on Twitter at @jkeiser2, email at [jkeiser@getchef.com](mailto:jkeiser@getchef.com)
200
235
 
201
- If you are interested in the Plan for Chef Metal, you can peruse our [Trello board](https://trello.com/b/GcSzW0GM/chef-metal)! Please add suggestions there, vote or comment on issues that are important to you, and feel free to contribute by picking up a card. Chat with me (jkeiser@opscode.com) if you would like some context on how to go about implementing a card, or just go hog wild and submit a PR :)
236
+ To contribute, just make a PR in the appropriate repo--also, make sure you've [signed the Chef Contributor License Agreement](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L) (quick couple of minutes online), since this is going into core Chef eventually. It takes some time to process, so if you've just done it, let me know in the PR :) If you already signed this for a Chef contribution, you don't need to do so again--if you're not sure, you can check for your name [here](https://wiki.opscode.com/display/chef/Approved+Contributors)!
237
+ Â
@@ -17,13 +17,16 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
17
17
  end
18
18
 
19
19
  action :allocate do
20
- new_driver.allocate_machine(action_handler, machine_spec, machine_options)
20
+ if current_driver && current_driver.driver_url != new_driver.driver_url
21
+ raise "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate."
22
+ end
23
+ new_driver.allocate_machine(action_handler, machine_spec, new_machine_options)
21
24
  machine_spec.save(action_handler)
22
25
  end
23
26
 
24
27
  action :ready do
25
28
  action_allocate
26
- machine = current_driver.ready_machine(action_handler, machine_spec, machine_options)
29
+ machine = current_driver.ready_machine(action_handler, machine_spec, current_machine_options)
27
30
  machine_spec.save(action_handler)
28
31
  machine
29
32
  end
@@ -56,7 +59,7 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
56
59
  end
57
60
 
58
61
  action :converge_only do
59
- machine = run_context.chef_metal.connect_to_machine(machine_spec, machine_options)
62
+ machine = run_context.chef_metal.connect_to_machine(machine_spec, current_machine_options)
60
63
  begin
61
64
  machine.converge(action_handler)
62
65
  ensure
@@ -66,35 +69,39 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
66
69
 
67
70
  action :stop do
68
71
  if current_driver
69
- current_driver.stop_machine(action_handler, machine_spec, machine_options)
72
+ current_driver.stop_machine(action_handler, machine_spec, current_machine_options)
70
73
  end
71
74
  end
72
75
 
73
76
  action :destroy do
74
77
  if current_driver
75
- current_driver.destroy_machine(action_handler, machine_spec, machine_options)
78
+ current_driver.destroy_machine(action_handler, machine_spec, current_machine_options)
76
79
  end
77
80
  end
78
81
 
82
+ attr_reader :machine_spec
83
+
79
84
  def new_driver
80
85
  run_context.chef_metal.driver_for(new_resource.driver)
81
86
  end
82
87
 
83
- def new_driver_config
84
- run_context.chef_metal.driver_config_for(new_resource.driver)
88
+ def current_driver
89
+ if machine_spec.driver_url
90
+ run_context.chef_metal.driver_for(machine_spec.driver_url)
91
+ end
85
92
  end
86
93
 
87
- def current_driver
88
- run_context.chef_metal.current_driver || (
89
- if machine_spec.driver_url
90
- run_context.chef_metal.driver_for_url(machine_spec.driver_url)
91
- end
92
- )
94
+ def new_machine_options
95
+ machine_options(new_driver)
93
96
  end
94
97
 
95
- attr_reader :machine_spec
98
+ def current_machine_options
99
+ if current_driver
100
+ machine_options(current_driver)
101
+ end
102
+ end
96
103
 
97
- def machine_options
104
+ def machine_options(driver)
98
105
  configs = []
99
106
  configs << {
100
107
  :convergence_options =>
@@ -111,7 +118,7 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
111
118
  end
112
119
  }
113
120
  configs << new_resource.machine_options if new_resource.machine_options
114
- configs << new_driver_config[:machine_options] if new_driver_config[:machine_options]
121
+ configs << driver.config[:machine_options] if driver.config[:machine_options]
115
122
  Cheffish::MergedConfig.new(*configs)
116
123
  end
117
124
 
@@ -25,7 +25,8 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
25
25
  action :allocate do
26
26
  by_new_driver.each do |driver, specs_and_options|
27
27
  driver.allocate_machines(action_handler, specs_and_options, parallelizer) do |machine_spec|
28
- machine_spec.save(action_handler)
28
+ prefixed_handler = ChefMetal::AddPrefixActionHandler.new(action_handler, "[#{machine_spec.name}] ")
29
+ machine_spec.save(prefixed_handler)
29
30
  end
30
31
  end
31
32
  end
@@ -38,7 +39,7 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
38
39
  with_ready_machines do |m|
39
40
  prefixed_handler = ChefMetal::AddPrefixActionHandler.new(action_handler, "[#{m[:spec].name}] ")
40
41
  machine[:machine].setup_convergence(prefixed_handler)
41
- m[:spec].save(action_handler)
42
+ m[:spec].save(prefixed_handler)
42
43
  Chef::Provider::Machine.upload_files(prefixed_handler, m[:machine], m[:files])
43
44
  end
44
45
  end
@@ -49,15 +50,17 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
49
50
  m[:machine].setup_convergence(prefixed_handler)
50
51
  m[:spec].save(action_handler)
51
52
  Chef::Provider::Machine.upload_files(prefixed_handler, m[:machine], m[:files])
53
+ # TODO only converge if machine was modified
52
54
  m[:machine].converge(prefixed_handler)
53
- m[:spec].save(action_handler)
55
+ m[:spec].save(prefixed_handler)
54
56
  end
55
57
  end
56
58
 
57
59
  action :converge_only do
58
60
  parallel_do(@machines) do |m|
61
+ prefixed_handler = ChefMetal::AddPrefixActionHandler.new(action_handler, "[#{m[:spec].name}] ")
59
62
  machine = run_context.chef_metal.connect_to_machine(m[:spec])
60
- machine.converge(action_handler)
63
+ machine.converge(prefixed_handler)
61
64
  end
62
65
  end
63
66
 
@@ -101,11 +104,22 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
101
104
 
102
105
  def by_new_driver
103
106
  result = {}
107
+ drivers = {}
104
108
  @machines.each do |m|
105
109
  if m[:desired_driver]
106
- driver = run_context.chef_metal.driver_for(m[:desired_driver])
110
+ drivers[m[:desired_driver]] ||= run_context.chef_metal.driver_for(m[:desired_driver])
111
+ driver = drivers[m[:desired_driver]]
112
+ # Check whether the current driver is same or different; we disallow
113
+ # moving a machine from one place to another.
114
+ if m[:spec].driver_url
115
+ drivers[m[:spec].driver_url] ||= run_context.chef_metal.driver_for(m[:spec].driver_url)
116
+ current_driver = drivers[m[:spec].driver_url]
117
+ if driver.driver_url != current_driver.driver_url
118
+ raise "Cannot move '#{m[:spec].name}' from #{current_driver.driver_url} to #{driver.driver_url}: machine moving is not supported. Destroy and recreate."
119
+ end
120
+ end
107
121
  result[driver] ||= {}
108
- result[driver][m[:spec]] = m[:options]
122
+ result[driver][m[:spec]] = m[:machine_options].call(driver)
109
123
  end
110
124
  end
111
125
  result
@@ -113,11 +127,13 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
113
127
 
114
128
  def by_current_driver
115
129
  result = {}
130
+ drivers = {}
116
131
  @machines.each do |m|
117
132
  if m[:spec].driver_url
118
- driver = run_context.chef_metal.driver_for_url(m[:spec].driver_url)
133
+ drivers[m[:spec].driver_url] ||= run_context.chef_metal.driver_for(m[:spec].driver_url)
134
+ driver = drivers[m[:spec].driver_url]
119
135
  result[driver] ||= {}
120
- result[driver][m[:spec]] = m[:options]
136
+ result[driver][m[:spec]] = m[:machine_options].call(driver)
121
137
  end
122
138
  end
123
139
  result
@@ -134,7 +150,7 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
134
150
  :spec => provider.machine_spec,
135
151
  :desired_driver => machine_resource.driver,
136
152
  :files => machine_resource.files,
137
- :options => provider.machine_options
153
+ :machine_options => proc { |driver| provider.machine_options(driver) }
138
154
  }
139
155
  elsif machine.is_a?(ChefMetal::MachineSpec)
140
156
  machine_spec = machine
@@ -142,7 +158,7 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
142
158
  :spec => machine_spec,
143
159
  :desired_driver => new_resource.driver,
144
160
  :files => new_resource.files,
145
- :options => new_machine_options
161
+ :machine_options => proc { |driver| machine_options(driver) }
146
162
  }
147
163
  else
148
164
  name = machine
@@ -152,23 +168,17 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
152
168
  :spec => machine_spec,
153
169
  :desired_driver => new_resource.driver,
154
170
  :files => new_resource.files,
155
- :options => new_machine_options
171
+ :machine_options => proc { |driver| machine_options(driver) }
156
172
  }
157
173
  end
158
- end.select { |m| !m.nil? }.to_a
174
+ end.to_a
159
175
  end
160
176
 
161
- def new_machine_options
162
- @new_machine_options ||= begin
163
- result = { :convergence_options => { :chef_server => new_resource.chef_server } }
164
- result = Chef::Mixin::DeepMerge.hash_only_merge(result, new_config[:machine_options]) if new_config[:machine_options]
165
- result = Chef::Mixin::DeepMerge.hash_only_merge(result, new_resource.machine_options)
166
- result
167
- end
168
- end
169
-
170
- def new_config
171
- @new_config ||= run_context.chef_metal.driver_config_for(new_resource.driver)
177
+ def machine_options(driver)
178
+ result = { :convergence_options => { :chef_server => new_resource.chef_server } }
179
+ result = Chef::Mixin::DeepMerge.hash_only_merge(result, run_context.chef_metal.config[:machine_options]) if run_context.chef_metal.config[:machine_options]
180
+ result = Chef::Mixin::DeepMerge.hash_only_merge(result, driver.config[:machine_options]) if driver.config && driver.config[:machine_options]
181
+ result = Chef::Mixin::DeepMerge.hash_only_merge(result, new_resource.machine_options)
182
+ result
172
183
  end
173
-
174
184
  end
@@ -41,4 +41,32 @@ class Chef::Resource::MachineBatch < Chef::Resource::LWRPBase
41
41
  def add_machine_options(options)
42
42
  @machine_options = Chef::Mixin::DeepMerge.hash_only_merge(@machine_options, options)
43
43
  end
44
+
45
+ # We override this because we want to hide @from_recipe and shorten @machines
46
+ # in error output.
47
+ def to_text
48
+ ivars = instance_variables.map { |ivar| ivar.to_sym } - HIDDEN_IVARS - [ :@from_recipe, :@machines ]
49
+ text = "# Declared in #{@source_line}\n\n"
50
+ text << self.class.dsl_name + "(\"#{name}\") do\n"
51
+ ivars.each do |ivar|
52
+ if (value = instance_variable_get(ivar)) && !(value.respond_to?(:empty?) && value.empty?)
53
+ value_string = value.respond_to?(:to_text) ? value.to_text : value.inspect
54
+ text << " #{ivar.to_s.sub(/^@/,'')} #{value_string}\n"
55
+ end
56
+ end
57
+ machine_names = @machines.map do |m|
58
+ if m.is_a?(ChefMetal::MachineSpec)
59
+ m.name
60
+ elsif m.is_a?(Chef::Resource::Machine)
61
+ m.name
62
+ else
63
+ m
64
+ end
65
+ end
66
+ text << " machines #{machine_names.inspect}\n"
67
+ [@not_if, @only_if].flatten.each do |conditional|
68
+ text << " #{conditional.to_text}\n"
69
+ end
70
+ text << "end\n"
71
+ end
44
72
  end
data/lib/chef_metal.rb CHANGED
@@ -30,23 +30,44 @@ module ChefMetal
30
30
  @@registered_driver_classes[name] = driver
31
31
  end
32
32
 
33
- def self.config_for_url(driver_url, config = Cheffish.profiled_config)
34
- if config && config[:drivers] && config[:drivers][driver_url]
35
- config = Cheffish::MergedConfig.new(config[:drivers][driver_url], config)
36
- end
37
- config || {}
38
- end
39
-
40
33
  def self.default_driver(config = Cheffish.profiled_config)
41
34
  driver_for_url(config[:driver], config)
42
35
  end
43
36
 
44
- def self.driver_for_url(driver_url, config = Cheffish.profiled_config)
45
- cluster_type = driver_url.split(':', 2)[0]
46
- require "chef_metal/driver_init/#{cluster_type}"
47
- driver_class = @@registered_driver_classes[cluster_type]
48
- config = config_for_url(driver_url, config)
49
- driver_class.from_url(driver_url, config || {})
37
+ def self.driver_for_url(driver_url, config = Cheffish.profiled_config, allow_different_config = false)
38
+ #
39
+ # Create and cache the driver
40
+ #
41
+ #
42
+ # Figure out the driver class
43
+ #
44
+ scheme = driver_url.split(':', 2)[0]
45
+ require "chef_metal/driver_init/#{scheme}"
46
+ driver_class = @@registered_driver_classes[scheme]
47
+
48
+ #
49
+ # Merge in any driver-specific config
50
+ #
51
+ if config[:drivers] && config[:drivers][driver_url]
52
+ config = Cheffish::MergedConfig.new(config[:drivers][driver_url], config)
53
+ end
54
+
55
+ #
56
+ # Canonicalize the URL
57
+ #
58
+ canonicalized_url, canonicalized_config = driver_class.canonicalize_url(driver_url, config)
59
+ config = canonicalized_config if canonicalized_config
60
+
61
+ #
62
+ # Merge in config from the canonicalized URL if it is different
63
+ #
64
+ if canonicalized_url != driver_url
65
+ if config[:drivers] && config[:drivers][canonicalized_url]
66
+ config = Cheffish::MergedConfig.new(config[:drivers][canonicalized_url], config)
67
+ end
68
+ end
69
+
70
+ driver_class.from_url(canonicalized_url, config)
50
71
  end
51
72
 
52
73
  def self.connect_to_machine(machine_spec, config = Cheffish.profiled_config)
@@ -13,10 +13,18 @@ module ChefMetal
13
13
 
14
14
  attr_reader :config
15
15
  attr_reader :drivers
16
+ attr_reader :current_driver
16
17
 
17
- with :driver
18
18
  with :machine_options
19
19
 
20
+ def with_driver(driver, options = nil, &block)
21
+ if drivers[driver] && options
22
+ raise "Driver #{driver} has already been created, options #{options} would be ignored!"
23
+ end
24
+ @current_driver = driver
25
+ @current_driver_options = options
26
+ end
27
+
20
28
  def auto_batch_machines
21
29
  if !@auto_batch_machines.nil?
22
30
  @auto_batch_machines
@@ -37,7 +45,7 @@ module ChefMetal
37
45
  if @current_machine_options
38
46
  @current_machine_options
39
47
  else
40
- driver_config_for(current_driver)[:machine_options] || {}
48
+ {}
41
49
  end
42
50
  end
43
51
 
@@ -49,15 +57,31 @@ module ChefMetal
49
57
  driver.is_a?(String) ? driver_for_url(driver) : driver
50
58
  end
51
59
 
52
- def driver_config_for(driver)
53
- ChefMetal.config_for_url(driver_for(driver).driver_url, config)
60
+ def connect_to_machine(name, chef_server = nil)
61
+ if name.is_a?(MachineSpec)
62
+ machine_spec = name
63
+ else
64
+ machine_spec = ChefMetal::ChefMachineSpec.get(name, chef_server)
65
+ end
66
+ ChefMetal.connect_to_machine(machine_spec, config)
54
67
  end
55
68
 
69
+ private
70
+
56
71
  def driver_for_url(driver_url)
57
72
  drivers[driver_url] ||= begin
58
- driver = ChefMetal.driver_for_url(driver_url, config)
73
+ if driver_url == @current_driver && @current_driver_options
74
+ # Use the driver options if available
75
+ merged_config = Cheffish::MergedConfig.new({ :driver_options => @current_driver_options }, config)
76
+ driver = ChefMetal.driver_for_url(driver_url, merged_config)
77
+ else
78
+ driver = ChefMetal.driver_for_url(driver_url, config)
79
+ end
59
80
  # Check the canonicalized driver_url from the driver
60
81
  if driver.driver_url != driver_url
82
+ if drivers[driver.driver_url] && @current_driver_options
83
+ raise "Canonical driver #{driver.driver_url} for #{driver_url} has already been created! Current options #{@current_driver_options} would be ignored."
84
+ end
61
85
  drivers[driver.driver_url] ||= driver
62
86
  else
63
87
  driver
@@ -65,15 +89,6 @@ module ChefMetal
65
89
  end
66
90
  end
67
91
 
68
- def connect_to_machine(name, chef_server = nil)
69
- if name.is_a?(MachineSpec)
70
- machine_spec = name
71
- else
72
- machine_spec = ChefMetal::ChefMachineSpec.get(name, chef_server)
73
- end
74
- ChefMetal.connect_to_machine(machine_spec, config)
75
- end
76
-
77
92
  def keys
78
93
  result = (config.keys || {}).dup
79
94
  Array(config.key_path) do |key_path|
@@ -173,6 +173,7 @@ module ChefMetal
173
173
  chef_server_url #{chef_server_url.inspect}
174
174
  node_name #{node_name.inspect}
175
175
  client_key #{convergence_options[:client_pem_path].inspect}
176
+ ssl_verify_mode :verify_none
176
177
  EOM
177
178
  end
178
179
  end
@@ -13,8 +13,8 @@ require 'chef/provider/machine_execute'
13
13
  class Chef
14
14
  module DSL
15
15
  module Recipe
16
- def with_driver(driver, &block)
17
- run_context.chef_metal.with_driver(driver, &block)
16
+ def with_driver(driver, options = nil, &block)
17
+ run_context.chef_metal.with_driver(driver, options, &block)
18
18
  end
19
19
 
20
20
  def with_machine_options(machine_options, &block)
@@ -109,11 +109,10 @@ module ChefMetal
109
109
  def make_url_available_to_remote(local_url)
110
110
  uri = URI(local_url)
111
111
  host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
112
- if host == '127.0.0.1' || host == '[::1]'
113
- unless session.forward.active_remotes.any? { |port, bind| port == uri.port && bind == '127.0.0.1' }
114
- # TODO IPv6
115
- Chef::Log.debug("Forwarding local server 127.0.0.1:#{uri.port} to port #{uri.port} on #{username}@#{host}")
116
- session.forward.remote(uri.port, '127.0.0.1', uri.port)
112
+ if host == '127.0.0.1' || host == '::1'
113
+ unless session.forward.active_remotes.any? { |port, bind| port == uri.port && bind == uri.host }
114
+ Chef::Log.debug("Forwarding local server #{uri.host}:#{uri.port} to port #{uri.port} on #{username}@#{self.host}")
115
+ session.forward.remote(uri.port, uri.host, uri.port)
117
116
  end
118
117
  end
119
118
  local_url
@@ -125,8 +124,9 @@ module ChefMetal
125
124
  Chef::Log.debug("Closing SSH session on #{username}@#{host}")
126
125
  @session.close
127
126
  rescue
127
+ ensure
128
+ @session = nil
128
129
  end
129
- @session = nil
130
130
  end
131
131
  end
132
132
 
@@ -136,37 +136,16 @@ module ChefMetal
136
136
  true
137
137
  rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
138
138
  Chef::Log.debug("#{username}@#{host} unavailable: network connection failed or broke: #{$!.inspect}")
139
+ disconnect
139
140
  false
140
141
  rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch
141
142
  Chef::Log.debug("#{username}@#{host} unavailable: SSH authentication error: #{$!.inspect} ")
143
+ disconnect
142
144
  false
143
145
  end
144
146
 
145
147
  protected
146
148
 
147
- def gateway?
148
- options.key?(:ssh_gateway) and ! options[:ssh_gateway].nil?
149
- end
150
-
151
- def gateway
152
- @gateway ||= begin
153
- gw_host, gw_user = options[:ssh_gateway].split('@').reverse
154
- gw_host, gw_port = gw_host.split(':')
155
- gw_user = ssh_options[:ssh_username] unless gw_user
156
-
157
- ssh_start_opts = { timeout:10 }.merge(ssh_options)
158
- ssh_start_opts[:port] = gw_port || 22
159
-
160
- Chef::Log.debug("Opening SSH gateway to #{gw_user}@#{gw_host} with options #{ssh_start_opts.inspect}")
161
- begin
162
- Net::SSH::Gateway.new(gw_host, gw_user, ssh_start_opts)
163
- rescue Errno::ETIMEDOUT
164
- Chef::Log.debug("Timed out connecting to gateway: #{$!}")
165
- raise InitialConnectTimeout.new($!)
166
- end
167
- end
168
- end
169
-
170
149
  def session
171
150
  @session ||= begin
172
151
  ssh_start_opts = { timeout:10 }.merge(ssh_options)
@@ -230,6 +209,29 @@ module ChefMetal
230
209
 
231
210
  attr_reader :original_error
232
211
  end
212
+
213
+ private
214
+
215
+ def gateway?
216
+ options.key?(:ssh_gateway) and ! options[:ssh_gateway].nil?
217
+ end
218
+
219
+ def gateway
220
+ gw_host, gw_user = options[:ssh_gateway].split('@').reverse
221
+ gw_host, gw_port = gw_host.split(':')
222
+ gw_user = ssh_options[:ssh_username] unless gw_user
223
+
224
+ ssh_start_opts = { timeout:10 }.merge(ssh_options)
225
+ ssh_start_opts[:port] = gw_port || 22
226
+
227
+ Chef::Log.debug("Opening SSH gateway to #{gw_user}@#{gw_host} with options #{ssh_start_opts.inspect}")
228
+ begin
229
+ Net::SSH::Gateway.new(gw_host, gw_user, ssh_start_opts)
230
+ rescue Errno::ETIMEDOUT
231
+ Chef::Log.debug("Timed out connecting to gateway: #{$!}")
232
+ raise InitialConnectTimeout.new($!)
233
+ end
234
+ end
233
235
  end
234
236
  end
235
237
  end
@@ -1,3 +1,3 @@
1
1
  module ChefMetal
2
- VERSION = '0.11.beta.6'
2
+ VERSION = '0.11.2.alpha.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clc-fork-chef-metal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.beta.6
4
+ version: 0.11.2.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wrock
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-29 00:00:00.000000000 Z
11
+ date: 2014-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -86,42 +86,42 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.5.beta.3
89
+ version: '0.5'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.5.beta.3
96
+ version: '0.5'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: chef-metal-fog
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 0.5.beta.2
103
+ version: '0.5'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 0.5.beta.2
110
+ version: '0.5'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: chef-metal-vagrant
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.4.beta
117
+ version: '0.4'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.4.beta
124
+ version: '0.4'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rspec
127
127
  requirement: !ruby/object:Gem::Requirement