spiceweasel 2.6.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +6 -14
  2. data/README.md +33 -9
  3. data/bin/spiceweasel +3 -3
  4. data/lib/spiceweasel.rb +3 -2
  5. data/lib/spiceweasel/berksfile.rb +6 -10
  6. data/lib/spiceweasel/cli.rb +174 -129
  7. data/lib/spiceweasel/clusters.rb +31 -23
  8. data/lib/spiceweasel/command.rb +23 -5
  9. data/lib/spiceweasel/command_helper.rb +36 -2
  10. data/lib/spiceweasel/config.rb +4 -3
  11. data/lib/spiceweasel/cookbooks.rb +76 -57
  12. data/lib/spiceweasel/data_bags.rb +100 -64
  13. data/lib/spiceweasel/environments.rb +78 -56
  14. data/lib/spiceweasel/execute.rb +6 -7
  15. data/lib/spiceweasel/extract_local.rb +59 -46
  16. data/lib/spiceweasel/knife.rb +21 -20
  17. data/lib/spiceweasel/log.rb +5 -5
  18. data/lib/spiceweasel/nodes.rb +261 -193
  19. data/lib/spiceweasel/roles.rb +107 -76
  20. data/lib/spiceweasel/version.rb +5 -3
  21. data/test/chef-repo/Berksfile +4 -0
  22. data/test/chef-repo/Berksfile.lock +10 -0
  23. data/test/chef-repo/PASSWORD +1 -0
  24. data/test/chef-repo/cookbooks/abc/CHANGELOG.md +13 -0
  25. data/test/chef-repo/cookbooks/abc/README.md +68 -0
  26. data/test/chef-repo/cookbooks/abc/metadata.rb +7 -0
  27. data/test/chef-repo/cookbooks/abc/recipes/default.rb +8 -0
  28. data/test/chef-repo/cookbooks/def/CHANGELOG.md +13 -0
  29. data/test/chef-repo/cookbooks/def/README.md +68 -0
  30. data/test/chef-repo/cookbooks/def/metadata.rb +7 -0
  31. data/test/chef-repo/cookbooks/def/recipes/default.rb +8 -0
  32. data/test/chef-repo/cookbooks/fail1/README.md +68 -0
  33. data/test/chef-repo/cookbooks/fail1/metadata.rb +9 -0
  34. data/test/chef-repo/cookbooks/fail2/README.md +68 -0
  35. data/test/chef-repo/cookbooks/fail2/metadata.rb +9 -0
  36. data/test/chef-repo/cookbooks/fail3/README.md +68 -0
  37. data/test/chef-repo/cookbooks/fail3/metadata.rb +9 -0
  38. data/test/chef-repo/cookbooks/ghi/CHANGELOG.md +13 -0
  39. data/test/chef-repo/cookbooks/ghi/README.md +68 -0
  40. data/test/chef-repo/cookbooks/ghi/metadata.rb +7 -0
  41. data/test/chef-repo/cookbooks/ghi/recipes/default.rb +8 -0
  42. data/test/chef-repo/cookbooks/jkl/CHANGELOG.md +13 -0
  43. data/test/chef-repo/cookbooks/jkl/README.md +68 -0
  44. data/test/chef-repo/cookbooks/jkl/metadata.rb +10 -0
  45. data/test/chef-repo/cookbooks/jkl/recipes/default.rb +8 -0
  46. data/test/chef-repo/cookbooks/mno/CHANGELOG.md +13 -0
  47. data/test/chef-repo/cookbooks/mno/README.md +68 -0
  48. data/test/chef-repo/cookbooks/mno/metadata.rb +9 -0
  49. data/test/chef-repo/cookbooks/mno/recipes/default.rb +8 -0
  50. data/test/chef-repo/data_bags/junk/README +1 -0
  51. data/test/chef-repo/data_bags/junk/abc.json +4 -0
  52. data/test/chef-repo/data_bags/junk/ade.json +4 -0
  53. data/test/chef-repo/data_bags/junk/afg.json +4 -0
  54. data/test/chef-repo/data_bags/junk/bcd.json +4 -0
  55. data/test/chef-repo/data_bags/junk/sub1/cde1.json +4 -0
  56. data/test/chef-repo/data_bags/junk/sub1/cde2.json +4 -0
  57. data/test/chef-repo/data_bags/junk/sub2/def1.json +4 -0
  58. data/test/chef-repo/data_bags/junk/sub2/def2.json +4 -0
  59. data/test/chef-repo/data_bags/users/README +1 -0
  60. data/test/chef-repo/data_bags/users/badjson.json +8 -0
  61. data/test/chef-repo/data_bags/users/failname.json +8 -0
  62. data/test/chef-repo/data_bags/users/mray.json +8 -0
  63. data/test/chef-repo/data_bags/users/ubuntu.json +8 -0
  64. data/test/chef-repo/environments/development.rb +2 -0
  65. data/test/chef-repo/environments/fail2.rb +8 -0
  66. data/test/chef-repo/environments/fail3.rb +2 -0
  67. data/test/chef-repo/environments/production-blue.json +177 -0
  68. data/test/chef-repo/environments/production-green.json +177 -0
  69. data/test/chef-repo/environments/production-red.json +177 -0
  70. data/test/chef-repo/environments/qa.rb +2 -0
  71. data/test/chef-repo/environments/sub/efg1.rb +2 -0
  72. data/test/chef-repo/environments/sub/efg2.json +177 -0
  73. data/test/chef-repo/fail-cookbook1.yml +19 -0
  74. data/test/chef-repo/fail-cookbook2.yml +21 -0
  75. data/test/chef-repo/fail-cookbook3.yml +37 -0
  76. data/test/chef-repo/fail-cookbook4.yml +37 -0
  77. data/test/chef-repo/fail-cookbook5.yml +10 -0
  78. data/test/chef-repo/fail-cookbook6.yml +9 -0
  79. data/test/chef-repo/fail-db1.yml +12 -0
  80. data/test/chef-repo/fail-db2.yml +10 -0
  81. data/test/chef-repo/fail-db3.yml +10 -0
  82. data/test/chef-repo/fail-db4.yml +10 -0
  83. data/test/chef-repo/fail-env1.yml +27 -0
  84. data/test/chef-repo/fail-env2.yml +27 -0
  85. data/test/chef-repo/fail-env3.yml +28 -0
  86. data/test/chef-repo/fail-env4.yml +28 -0
  87. data/test/chef-repo/fail-roles1.yml +22 -0
  88. data/test/chef-repo/fail-roles2.yml +21 -0
  89. data/test/chef-repo/fail-roles3.yml +23 -0
  90. data/test/chef-repo/fail-roles4.yml +23 -0
  91. data/test/chef-repo/fail-roles5.yml +23 -0
  92. data/test/chef-repo/infrastructure.yml +43 -0
  93. data/test/chef-repo/nodes/boxy.lab.atx.json +1756 -0
  94. data/test/chef-repo/nodes/guenter.home.atx.json +2503 -0
  95. data/test/chef-repo/roles/README +1 -0
  96. data/test/chef-repo/roles/base.rb +18 -0
  97. data/test/chef-repo/roles/base2.rb +16 -0
  98. data/test/chef-repo/roles/base3.rb +17 -0
  99. data/test/chef-repo/roles/base4.rb +15 -0
  100. data/test/chef-repo/roles/fail1.rb +8 -0
  101. data/test/chef-repo/roles/fail2.rb +5 -0
  102. data/test/chef-repo/roles/fail3.rb +5 -0
  103. data/test/chef-repo/roles/sub/bw2.json +21 -0
  104. data/test/chef-repo/roles/sub/bwi1.json +20 -0
  105. data/test/chef-repo/roles/tc.rb +13 -0
  106. data/test/examples/cluster-file-example.yml +14 -0
  107. data/test/examples/example-cluster.yml +8 -0
  108. data/test/examples/example.json +127 -0
  109. data/test/examples/example.rb +128 -0
  110. data/test/examples/example.yml +67 -0
  111. data/test/examples/google-example.yml +33 -0
  112. data/test/examples/joyent-vsphere-example.yml +15 -0
  113. data/test/examples/knife.yml +7 -0
  114. data/test/examples/kvm-example.yml +22 -0
  115. data/test/examples/node-example.yml +23 -0
  116. data/test/examples/php-quick-start.yml +83 -0
  117. data/test/extract-repo/Berksfile +4 -0
  118. data/test/extract-repo/Berksfile.lock +10 -0
  119. data/test/extract-repo/cookbooks/abc/CHANGELOG.md +13 -0
  120. data/test/extract-repo/cookbooks/abc/README.md +68 -0
  121. data/test/extract-repo/cookbooks/abc/metadata.rb +7 -0
  122. data/test/extract-repo/cookbooks/abc/recipes/default.rb +8 -0
  123. data/test/extract-repo/cookbooks/def/CHANGELOG.md +13 -0
  124. data/test/extract-repo/cookbooks/def/README.md +68 -0
  125. data/test/extract-repo/cookbooks/def/metadata.rb +7 -0
  126. data/test/extract-repo/cookbooks/def/recipes/default.rb +8 -0
  127. data/test/extract-repo/cookbooks/ghi/CHANGELOG.md +13 -0
  128. data/test/extract-repo/cookbooks/ghi/README.md +68 -0
  129. data/test/extract-repo/cookbooks/ghi/metadata.rb +7 -0
  130. data/test/extract-repo/cookbooks/ghi/recipes/default.rb +8 -0
  131. data/test/extract-repo/cookbooks/jkl/CHANGELOG.md +13 -0
  132. data/test/extract-repo/cookbooks/jkl/README.md +68 -0
  133. data/test/extract-repo/cookbooks/jkl/metadata.rb +10 -0
  134. data/test/extract-repo/cookbooks/jkl/recipes/default.rb +8 -0
  135. data/test/extract-repo/cookbooks/mno/CHANGELOG.md +13 -0
  136. data/test/extract-repo/cookbooks/mno/README.md +68 -0
  137. data/test/extract-repo/cookbooks/mno/metadata.rb +9 -0
  138. data/test/extract-repo/cookbooks/mno/recipes/default.rb +8 -0
  139. data/test/extract-repo/data_bags/junk/README +1 -0
  140. data/test/extract-repo/data_bags/junk/abc.json +4 -0
  141. data/test/extract-repo/data_bags/junk/ade.json +4 -0
  142. data/test/extract-repo/data_bags/junk/afg.json +4 -0
  143. data/test/extract-repo/data_bags/junk/bcd.json +4 -0
  144. data/test/extract-repo/data_bags/junk/sub1/cde1.json +4 -0
  145. data/test/extract-repo/data_bags/junk/sub1/cde2.json +4 -0
  146. data/test/extract-repo/data_bags/junk/sub2/def1.json +4 -0
  147. data/test/extract-repo/data_bags/junk/sub2/def2.json +4 -0
  148. data/test/extract-repo/data_bags/users/README +1 -0
  149. data/test/extract-repo/data_bags/users/mray.json +8 -0
  150. data/test/extract-repo/data_bags/users/ubuntu.json +8 -0
  151. data/test/extract-repo/environments/development.rb +2 -0
  152. data/test/extract-repo/environments/production-blue.json +177 -0
  153. data/test/extract-repo/environments/production-green.json +177 -0
  154. data/test/extract-repo/environments/production-red.json +177 -0
  155. data/test/extract-repo/environments/qa.rb +2 -0
  156. data/test/extract-repo/environments/sub/efg1.rb +2 -0
  157. data/test/extract-repo/environments/sub/efg2.json +177 -0
  158. data/test/extract-repo/nodes/boxy.lab.atx.json +1756 -0
  159. data/test/extract-repo/nodes/guenter.home.atx.json +2503 -0
  160. data/test/extract-repo/roles/README +1 -0
  161. data/test/extract-repo/roles/base.rb +18 -0
  162. data/test/extract-repo/roles/base2.rb +16 -0
  163. data/test/extract-repo/roles/base3.rb +17 -0
  164. data/test/extract-repo/roles/base4.rb +16 -0
  165. data/test/extract-repo/roles/sub/bw2.json +21 -0
  166. data/test/extract-repo/roles/sub/bwi1.json +20 -0
  167. data/test/extract-repo/roles/tc.rb +13 -0
  168. data/test/extract-repo2/cookbooks/README.md +1 -0
  169. data/test/extract-repo2/data_bags/README.md +1 -0
  170. data/test/extract-repo2/environments/README.md +1 -0
  171. data/test/extract-repo2/nodes/README.md +1 -0
  172. data/test/extract-repo2/roles/README.md +1 -0
  173. metadata +357 -67
  174. data/spec/bin/chef_client_spec.rb +0 -72
  175. data/spec/bin/google_spec.rb +0 -105
  176. data/spec/bin/joyent-vsphere_spec.rb +0 -25
  177. data/spec/bin/knife_spec.rb +0 -18
  178. data/spec/bin/kvm_spec.rb +0 -29
  179. data/spec/bin/node_spec.rb +0 -108
  180. data/spec/bin/spiceweasel_spec.rb +0 -136
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDZhOGZjMDFmZjhhZTQ2ZTAwYmU0NmQyNzNjNTczNWE0MDIyZjVjOA==
5
- data.tar.gz: !binary |-
6
- MGNjYWFiMzVjODZjMzAwYTdmMGYyMDM5ZTBhZmRmYjM0MzEwODg0NQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MjY5YjBhOGRlNmViZjk3MGVmNDg3MjA1NjBmNTI0MGU4NmM3NzYwZjdhNzU3
10
- Mzc4M2Q0OGFhNTJjMzNkZDE5NjZkNWJhMzIyOTVkNjg4OTIyYTI3NzViYjQy
11
- MGM0NTE5NzNjY2I4ZmE1NmMzYmNlNjYwZDhiNTU4MmM0NjAxZWE=
12
- data.tar.gz: !binary |-
13
- MDkzOWM4NmExM2E3YTQ5ZDdmZTA2OTAxNDljYTNjNmI3NzNiYzk4OTIyZTQ3
14
- Y2Q0MWY3NGRkMjBmMjMyY2ZiZjZjOGM5MWE0ODYwOTA4ZTNlMzMxN2FhZWVm
15
- YWY5MDY3NjVmZWE1YTNhYzIwMjhlNDczOTMyYzAwMTMyNjNkMmE=
2
+ SHA1:
3
+ metadata.gz: 41902e9f8f3972b7bce55d55942f28442ccf3fa6
4
+ data.tar.gz: b6c12529132a69df2ec49be11fab0b914de47c2c
5
+ SHA512:
6
+ metadata.gz: 227150354c6f3603d256eb3a5ce3a9399759c4e58c7777257a2c11d7f862ee354829f40d13569cc0b677153569cfa566fc87d75a174661ea0351d467af2c9da1
7
+ data.tar.gz: 7fd3445f66ad0be1845bee308688fcc74f3cd0e620220473cf1d730f55e6b37af12e3a99f6a412035a18d151b24488f2a43a9147e1517cd2ba63f5ffd4f41da6
data/README.md CHANGED
@@ -17,7 +17,7 @@ Written and tested with the Chef 11.x series (previous versions of Chef may stil
17
17
 
18
18
  # File Syntax #
19
19
 
20
- The syntax for the Spiceweasel file may be Ruby, JSON or YAML format of Chef primitives describing what is to be instantiated. Please refer to the [examples/example.json](https://github.com/mattray/spiceweasel/blob/master/examples/example.json) or [examples/example.yml](https://github.com/mattray/spiceweasel/blob/master/examples/example.yml) for examples of the same infrastructure. Each subsection below shows the YAML syntax converted to knife commands.
20
+ The syntax for the Spiceweasel file may be Ruby, JSON or YAML format of Chef primitives describing what is to be instantiated. Please refer to the [test/examples/example.json](https://github.com/mattray/spiceweasel/blob/master/test/examples/example.json) or [test/examples/example.yml](https://github.com/mattray/spiceweasel/blob/master/test/examples/example.yml) for examples of the same infrastructure. Each subsection below shows the YAML syntax converted to knife commands.
21
21
 
22
22
  ## Cookbooks ##
23
23
 
@@ -169,9 +169,9 @@ produces the knife commands
169
169
  knife bootstrap serverA -i ~/.ssh/mray.pem -x user --sudo -r 'role[base]'
170
170
  knife bootstrap serverB -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
171
171
  knife bootstrap serverC -i ~/.ssh/mray.pem -x user --sudo -E production -r 'role[base]'
172
- knife rackspace server create --image 49 --flavor 2 --node-name rs1.example.com -r 'recipe[mysql],role[monitoring]'
173
- knife rackspace server create --image 49 --flavor 2 --node-name rs2.example.com -r 'recipe[mysql],role[monitoring]'
174
- knife rackspace server create --image 49 --flavor 2 --node-name rs3.example.com -r 'recipe[mysql],role[monitoring]'
172
+ knife rackspace server create --image 49 --flavor 2 --node-name db1.example.com -r 'recipe[mysql],role[monitoring]'
173
+ knife rackspace server create --image 49 --flavor 2 --node-name db2.example.com -r 'recipe[mysql],role[monitoring]'
174
+ knife rackspace server create --image 49 --flavor 2 --node-name db3.example.com -r 'recipe[mysql],role[monitoring]'
175
175
  knife bootstrap windows winrm winboxA -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
176
176
  knife bootstrap windows ssh winboxB -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
177
177
  knife bootstrap windows ssh winboxC -x Administrator -P 'super_secret_password' -r 'role[base],role[iisserver]'
@@ -218,7 +218,7 @@ clusters:
218
218
  produces the knife commands
219
219
 
220
220
  ```
221
- knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-8af0f326 -f m1.medium -E amazon
221
+ knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-8af0f326 -f m1.medium -E amazon -r 'role[mysql]'
222
222
  knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -E amazon -r 'role[webserver],recipe[mysql::client]'
223
223
  knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -E amazon -r 'role[webserver],recipe[mysql::client]'
224
224
  knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7000f019 -f m1.small -E amazon -r 'role[webserver],recipe[mysql::client]'
@@ -226,6 +226,30 @@ knife ec2 server create -S mray -i ~/.ssh/mray.pem -x ubuntu -G default -I ami-7
226
226
 
227
227
  Another use of `clusters` is with the `--cluster-file` option, which will allow the use of a different file to define the members of the cluster. If there are any `nodes` or `clusters` defined in the primary manifest file, they will be removed and the content of the `--cluster-file` will be used instead. This allows you to switch the target destination of infrastructure by picking different `--cluster-file` endpoints.
228
228
 
229
+ ## options ##
230
+
231
+ The `options` section provides the ability to pass global options to all nodes being created.
232
+
233
+ ```
234
+ options: -i ~/.ssh/mray.pem
235
+ nodes:
236
+ - serverA:
237
+ run_list: role[base]
238
+ options: -x user --sudo
239
+ clusters:
240
+ - amazon:
241
+ - ec2 1:
242
+ run_list: role[mysql]
243
+ options: -S mray -x ubuntu -G default -I ami-8af0f326 -f m1.medium
244
+ ```
245
+
246
+ produces the knife commands
247
+
248
+ ```
249
+ knife bootstrap serverA -x user --sudo -r -i ~/.ssh/mray.pem 'role[base]'
250
+ knife ec2 server create -S mray -x ubuntu -G default -I ami-8af0f326 -f m1.medium -E amazon -i ~/.ssh/mray.pem -r 'role[mysql]'
251
+ ```
252
+
229
253
  ## knife ##
230
254
 
231
255
  The `knife` section allows you to run arbitrary knife commands after you have deployed the infrastructure specified in the rest of the manifest. Validation is done to ensure that the knife commands called are installed on the system. The example YAML snippet
@@ -318,7 +342,7 @@ This provides verbose debugging messages.
318
342
 
319
343
  ## -d/--delete ##
320
344
 
321
- The `delete` option will generate the knife commands to delete the infrastructure described in the manifest. This includes each cookbook, environment, role, data bag and node listed. Node deletion will specify individual nodes and their clients, and attempt to pass the list of nodes to the cloud provider for deletion, and finish with `knife node bulk delete`. If you are mixing individual nodes with cloud provider nodes it is possible that nodes may be missed from cloud provider deletion and you should double-check (ie. `knife ec2 server list`).
345
+ The `delete` option will generate the knife commands to delete the infrastructure described in the manifest. This includes each cookbook, environment, role, data bag and node listed. Node deletion will specify individual nodes and their clients, and attempt to pass the list of nodes to the cloud provider for deletion, and finish with `knife node bulk delete`. If you are mixing individual nodes with cloud provider nodes it is possible that nodes may be missed from cloud provider deletion and you should double-check (ie. `knife ec2 server list`). Some knife plugins do not use the node name as the ID, so they may fail at deletion (knife-rackspace for example).
322
346
 
323
347
  ## -e/--execute ##
324
348
 
@@ -368,15 +392,15 @@ Print the version of spiceweasel currently installed.
368
392
 
369
393
  Spiceweasel uses [RSpec](http://rspec.info/) for testing. You should run the following before commiting.
370
394
 
371
- $ rspec
395
+ $ rspec test
372
396
 
373
397
  # License and Author #
374
398
 
375
399
  | | |
376
400
  |:---------------------|:---------------------------------------------------|
377
- | **Author** | Matt Ray (<matt@opscode.com>) |
401
+ | **Author** | Matt Ray (<matt@getchef.com>) |
378
402
  | | |
379
- | **Copyright** | Copyright (c) 2011-2013, Opscode, Inc. |
403
+ | **Copyright** | Copyright (c) 2011-2014, Chef Software, Inc. |
380
404
 
381
405
  Licensed under the Apache License, Version 2.0 (the "License");
382
406
  you may not use this file except in compliance with the License.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
-
2
+ # encoding: UTF-8
3
3
  #
4
- # Author:: Matt Ray (<matt@opscode.com>)
4
+ # Author:: Matt Ray (<matt@getchef.com>)
5
5
  #
6
- # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
6
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
9
9
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2013, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2013-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -17,15 +18,15 @@
17
18
  #
18
19
 
19
20
  module Spiceweasel
21
+ # load and parse berksfile
20
22
  class Berksfile
21
-
22
23
  attr_reader :create
23
24
  attr_reader :delete
24
25
  attr_reader :cookbook_list
25
26
 
26
27
  include CommandHelper
27
28
 
28
- def initialize(berkshelf=nil)
29
+ def initialize(berkshelf = nil)
29
30
  @create = []
30
31
  @delete = []
31
32
  @cookbook_list = {}
@@ -48,11 +49,7 @@ module Spiceweasel
48
49
  create_command("berks upload #{berks_options}")
49
50
  Berkshelf.ui.mute do
50
51
  Spiceweasel::Log.debug("berkshelf resolving dependencies: #{resolve_opts}")
51
- if(Gem::Version.new(Berkshelf::VERSION) >= Gem::Version.new('2.0.0'))
52
- ckbks = berks.install(resolve_opts)
53
- else
54
- ckbks = berks.resolve(resolve_opts)
55
- end
52
+ ckbks = berks.install
56
53
  ckbks.each do |cb|
57
54
  @cookbook_list[cb.cookbook_name] = cb.version
58
55
  delete_command("knife cookbook#{Spiceweasel::Config[:knife_options]} delete #{cb.cookbook_name} #{cb.version} -a -y")
@@ -60,5 +57,4 @@ module Spiceweasel
60
57
  end
61
58
  end
62
59
  end
63
-
64
60
  end
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2011-2013, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -17,10 +18,9 @@
17
18
  #
18
19
 
19
20
  require 'mixlib/cli'
20
- require 'yajl/json_gem'
21
+ require 'ffi_yajl'
21
22
  require 'yaml'
22
23
 
23
- require 'spiceweasel'
24
24
  require 'spiceweasel/command_helper'
25
25
  require 'spiceweasel/cookbooks'
26
26
  require 'spiceweasel/berksfile'
@@ -34,179 +34,187 @@ require 'spiceweasel/extract_local'
34
34
  require 'spiceweasel/execute'
35
35
 
36
36
  module Spiceweasel
37
+ # parse and execute cli options
37
38
  class CLI
38
39
  include Mixlib::CLI
39
40
 
41
+ MANIFEST_OPTIONS = %w(cookbooks environments roles data_bags nodes clusters knife)
42
+
40
43
  banner('Usage: spiceweasel [option] file
41
44
  spiceweasel [option] --extractlocal')
42
45
 
43
46
  option :clusterfile,
44
- :long => '--cluster-file file',
45
- :description => 'Specify an additional cluster manifest file, overriding any other node or cluster definitions'
47
+ long: '--cluster-file file',
48
+ description: 'Specify an additional cluster manifest file, overriding any other node or cluster definitions'
46
49
 
47
50
  option :debug,
48
- :long => '--debug',
49
- :description => 'Verbose debugging messages',
50
- :boolean => true
51
+ long: '--debug',
52
+ description: 'Verbose debugging messages',
53
+ boolean: true
51
54
 
52
55
  option :bulkdelete,
53
- :long => '--bulkdelete',
54
- :description => 'Delete all nodes for the provider(s) in the infrastructure',
55
- :boolean => false
56
+ long: '--bulkdelete',
57
+ description: 'Delete all nodes for the provider(s) in the infrastructure',
58
+ boolean: false
56
59
 
57
60
  option :attribute,
58
- :short => '-a',
59
- :long => '--attribute ATTR',
60
- :description => "The attribute to use for opening the connection - default depends on the context. Used in conjunction with '--chef-client'"
61
+ short: '-a',
62
+ long: '--attribute ATTR',
63
+ description: "The attribute to use for opening the connection - default depends on the context. Used in conjunction with '--chef-client'"
61
64
 
62
65
  option :chefclient,
63
- :long => '--chef-client',
64
- :description => 'Print the knife commands to run chef-client on the nodes of the infrastructure',
65
- :boolean => true
66
+ long: '--chef-client',
67
+ description: 'Print the knife commands to run chef-client on the nodes of the infrastructure',
68
+ boolean: true
66
69
 
67
70
  option :delete,
68
- :short => '-d',
69
- :long => '--delete',
70
- :description => 'Print the knife commands to delete the infrastructure',
71
- :boolean => true
71
+ short: '-d',
72
+ long: '--delete',
73
+ description: 'Print the knife commands to delete the infrastructure',
74
+ boolean: true
72
75
 
73
76
  option :execute,
74
- :short => '-e',
75
- :long => '--execute',
76
- :description => 'Execute the knife commands to create the infrastructure directly',
77
- :boolean => true
77
+ short: '-e',
78
+ long: '--execute',
79
+ description: 'Execute the knife commands to create the infrastructure directly',
80
+ boolean: true
78
81
 
79
82
  option :extractlocal,
80
- :long => '--extractlocal',
81
- :description => 'Use contents of local chef repository directories to generate knife commands to build infrastructure'
83
+ long: '--extractlocal',
84
+ description: 'Use contents of local chef repository directories to generate knife commands to build infrastructure'
82
85
 
83
86
  option :extractjson,
84
- :long => '--extractjson',
85
- :description => 'Use contents of local chef repository directories to generate JSON spiceweasel manifest'
87
+ long: '--extractjson',
88
+ description: 'Use contents of local chef repository directories to generate JSON spiceweasel manifest'
86
89
 
87
90
  option :extractyaml,
88
- :long => '--extractyaml',
89
- :description => 'Use contents of local chef repository directories to generate YAML spiceweasel manifest'
91
+ long: '--extractyaml',
92
+ description: 'Use contents of local chef repository directories to generate YAML spiceweasel manifest'
90
93
 
91
94
  option :help,
92
- :short => '-h',
93
- :long => '--help',
94
- :description => 'Show this message',
95
- :on => :tail,
96
- :boolean => true,
97
- :show_options => true,
98
- :exit => 0
95
+ short: '-h',
96
+ long: '--help',
97
+ description: 'Show this message',
98
+ on: :tail,
99
+ boolean: true,
100
+ show_options: true,
101
+ exit: 0
99
102
 
100
103
  option :knifeconfig,
101
- :short => '-c CONFIG',
102
- :long => '--knifeconfig CONFIG',
103
- :description => 'Specify the knife.rb configuration file'
104
+ short: '-c CONFIG',
105
+ long: '--knifeconfig CONFIG',
106
+ description: 'Specify the knife.rb configuration file'
104
107
 
105
108
  option :log_level,
106
- :short => "-l LEVEL",
107
- :long => "--loglevel LEVEL",
108
- :description => "Set the log level (debug, info, warn, error, fatal)",
109
- :proc => lambda { |l| l.to_sym }
109
+ short: '-l LEVEL',
110
+ long: '--loglevel LEVEL',
111
+ description: 'Set the log level (debug, info, warn, error, fatal)',
112
+ proc: lambda { |l| l.to_sym } # rubocop:disable Lambda
110
113
 
111
114
  option :log_location,
112
- :short => "-L LOGLOCATION",
113
- :long => "--logfile LOGLOCATION",
114
- :description => "Set the log file location, defaults to STDOUT",
115
- :proc => nil
115
+ short: '-L LOGLOCATION',
116
+ long: '--logfile LOGLOCATION',
117
+ description: 'Set the log file location, defaults to STDOUT',
118
+ proc: nil
116
119
 
117
120
  option :node_only,
118
- :long => '--node-only',
119
- :description => 'Create node(s) on the server, do not bootstrap',
120
- :boolean => false
121
+ long: '--node-only',
122
+ description: 'Create node(s) on the server, do not bootstrap',
123
+ boolean: false
121
124
 
122
125
  option :novalidation,
123
- :long => '--novalidation',
124
- :description => 'Disable validation',
125
- :boolean => true
126
+ long: '--novalidation',
127
+ description: 'Disable validation',
128
+ boolean: true
129
+
130
+ option :only,
131
+ long: '--only ONLY_LIST',
132
+ description: "Comma separated list of manifest components to apply. #{MANIFEST_OPTIONS}",
133
+ proc: lambda { |o| o.split(/[\s,]+/) },
134
+ default: []
126
135
 
127
136
  option :parallel,
128
- :long => '--parallel',
129
- :description => "Use the GNU 'parallel' command to parallelize 'knife VENDOR server create' commands where applicable",
130
- :boolean => true
137
+ long: '--parallel',
138
+ description: "Use the GNU 'parallel' command to parallelize 'knife VENDOR server create' commands where applicable",
139
+ boolean: true
131
140
 
132
141
  option :rebuild,
133
- :short => '-r',
134
- :long => '--rebuild',
135
- :description => 'Print the knife commands to delete and recreate the infrastructure',
136
- :boolean => true
142
+ short: '-r',
143
+ long: '--rebuild',
144
+ description: 'Print the knife commands to delete and recreate the infrastructure',
145
+ boolean: true
137
146
 
138
147
  option :serverurl,
139
- :short => '-s URL',
140
- :long => '--server-url URL',
141
- :description => 'Specify the Chef Server URL'
148
+ short: '-s URL',
149
+ long: '--server-url URL',
150
+ description: 'Specify the Chef Server URL'
142
151
 
143
152
  option :siteinstall,
144
- :long => '--siteinstall',
145
- :description => "Use the 'install' command with 'knife cookbook site' instead of the default 'download'",
146
- :boolean => true
153
+ long: '--siteinstall',
154
+ description: "Use the 'install' command with 'knife cookbook site' instead of the default 'download'",
155
+ boolean: true
147
156
 
148
157
  option :timeout,
149
- :short => '-T seconds',
150
- :long => '--timeout',
151
- :description => "Specify the maximum number of seconds a command is allowed to run without producing output. Default is 300 seconds",
152
- :default => 300
158
+ short: '-T seconds',
159
+ long: '--timeout',
160
+ description: 'Specify the maximum number of seconds a command is allowed to run without producing output. Default is 300 seconds',
161
+ default: 300
153
162
 
154
163
  option :version,
155
- :short => '-v',
156
- :long => '--version',
157
- :description => 'Show spiceweasel version',
158
- :boolean => true,
159
- :proc => lambda { |v| puts "Spiceweasel: #{::Spiceweasel::VERSION}" },
160
- :exit => 0
164
+ short: '-v',
165
+ long: '--version',
166
+ description: 'Show spiceweasel version',
167
+ boolean: true,
168
+ proc: ->() { puts "Spiceweasel: #{::Spiceweasel::VERSION}" },
169
+ exit: 0
161
170
 
162
171
  option :cookbook_directory,
163
- :short => '-C COOKBOOK_DIR',
164
- :long => '--cookbook-dir COOKBOOK_DIR',
165
- :description => 'Set cookbook directory. Specify multiple times for multiple directories.',
166
- :proc => lambda { |v|
167
- Spiceweasel::Config[:cookbook_dir] ||= []
168
- Spiceweasel::Config[:cookbook_dir] << v
169
- Spiceweasel::Config[:cookbook_dir].uniq!
170
- }
172
+ short: '-C COOKBOOK_DIR',
173
+ long: '--cookbook-dir COOKBOOK_DIR',
174
+ description: 'Set cookbook directory. Specify multiple times for multiple directories.',
175
+ proc: lambda { |v| # rubocop:disable Blocks
176
+ Spiceweasel::Config[:cookbook_dir] ||= []
177
+ Spiceweasel::Config[:cookbook_dir] << v
178
+ Spiceweasel::Config[:cookbook_dir].uniq!
179
+ }
171
180
 
172
181
  option :unique_id,
173
- :long => '--unique-id UID',
174
- :description => 'Unique ID generally used for ruby based configs'
182
+ long: '--unique-id UID',
183
+ description: 'Unique ID generally used for ruby based configs'
175
184
 
176
- def run
185
+ def run # rubocop:disable CyclomaticComplexity
177
186
  if Spiceweasel::Config[:extractlocal] || Spiceweasel::Config[:extractjson] || Spiceweasel::Config[:extractyaml]
178
187
  manifest = Spiceweasel::ExtractLocal.parse_objects
179
188
  else
180
- manifest = parse_and_validate_input(get_manifest())
189
+ manifest = parse_and_validate_input(find_manifest)
181
190
  if Spiceweasel::Config[:clusterfile]
182
191
  # if we have a cluster file, override any nodes or clusters in the original manifest
183
192
  manifest['nodes'] = manifest['clusters'] = {}
184
193
  manifest.merge!(parse_and_validate_input(Spiceweasel::Config[:clusterfile]))
185
194
  end
186
195
  end
196
+
187
197
  Spiceweasel::Log.debug("file manifest: #{manifest}")
188
198
 
199
+ manifest = process_only(manifest)
200
+
189
201
  create, delete = process_manifest(manifest)
190
202
 
203
+ evaluate_configuration(create, delete, manifest)
204
+
205
+ exit 0
206
+ end
207
+
208
+ def evaluate_configuration(create, delete, manifest)
191
209
  case
192
210
  when Spiceweasel::Config[:extractjson]
193
211
  puts JSON.pretty_generate(manifest)
194
212
  when Spiceweasel::Config[:extractyaml]
195
- puts manifest.to_yaml
213
+ puts manifest.to_yaml unless manifest.empty?
196
214
  when Spiceweasel::Config[:delete]
197
- if Spiceweasel::Config[:execute]
198
- Execute.new(delete)
199
- else
200
- puts delete unless delete.empty?
201
- end
215
+ do_config_execute_delete(delete)
202
216
  when Spiceweasel::Config[:rebuild]
203
- if Spiceweasel::Config[:execute]
204
- Execute.new(delete)
205
- Execute.new(create)
206
- else
207
- puts delete unless delete.empty?
208
- puts create unless create.empty?
209
- end
217
+ do_execute_rebuild(create, delete)
210
218
  else
211
219
  if Spiceweasel::Config[:execute]
212
220
  Execute.new(create)
@@ -214,20 +222,36 @@ module Spiceweasel
214
222
  puts create unless create.empty?
215
223
  end
216
224
  end
225
+ end
217
226
 
218
- exit 0
227
+ def do_execute_rebuild(create, delete)
228
+ if Spiceweasel::Config[:execute]
229
+ Execute.new(delete)
230
+ Execute.new(create)
231
+ else
232
+ puts delete unless delete.empty?
233
+ puts create unless create.empty?
234
+ end
235
+ end
236
+
237
+ def do_config_execute_delete(delete)
238
+ if Spiceweasel::Config[:execute]
239
+ Execute.new(delete)
240
+ else
241
+ puts delete unless delete.empty?
242
+ end
219
243
  end
220
244
 
221
- def initialize(argv=[])
245
+ def initialize(_argv = [])
222
246
  super()
223
247
  parse_and_validate_options
224
248
  Config.merge!(@config)
225
249
  configure_logging
226
- Spiceweasel::Log.debug("Validation of the manifest has been turned off.") if Spiceweasel::Config[:novalidation]
250
+ Spiceweasel::Log.debug('Validation of the manifest has been turned off.') if Spiceweasel::Config[:novalidation]
227
251
  end
228
252
 
229
253
  def parse_and_validate_options
230
- ARGV << "-h" if ARGV.empty?
254
+ ARGV << '-h' if ARGV.empty?
231
255
  begin
232
256
  parse_options
233
257
  # Load knife configuration if using knife config
@@ -237,7 +261,9 @@ module Spiceweasel
237
261
  Chef::Config[:verbosity] = 0
238
262
  Chef::Config[:log_level] = :error
239
263
  if @config[:knifeconfig]
240
- knife.read_config_file(@config[:knifeconfig])
264
+ # 11.8 and later
265
+ fetcher = Chef::ConfigFetcher.new(@config[:knifeconfig], Chef::Config.config_file_jail)
266
+ knife.read_config(fetcher.read_config, @config[:knifeconfig])
241
267
  Spiceweasel::Config[:knife_options] = " -c #{@config[:knifeconfig]} "
242
268
  else
243
269
  knife.configure_chef
@@ -265,19 +291,20 @@ module Spiceweasel
265
291
  end
266
292
  end
267
293
 
268
- def parse_and_validate_input(file)
294
+ def parse_and_validate_input(file) # rubocop:disable CyclomaticComplexity
269
295
  begin
270
296
  Spiceweasel::Log.debug("file: #{file}")
271
- if !File.file?(file)
297
+ unless File.file?(file)
272
298
  STDERR.puts "ERROR: #{file} is an invalid manifest file, please check your path."
273
299
  exit(-1)
274
300
  end
275
- if (file.end_with?(".yml"))
301
+ output = nil
302
+ if file.end_with?('.yml')
276
303
  output = YAML.load_file(file)
277
- elsif (file.end_with?(".json"))
304
+ elsif file.end_with?('.json')
278
305
  output = JSON.parse(File.read(file))
279
- elsif (file.end_with?(".rb"))
280
- output = self.instance_eval(IO.read(file), file, 1)
306
+ elsif file.end_with?('.rb')
307
+ output = instance_eval(IO.read(file), file, 1)
281
308
  output = JSON.parse(JSON.dump(output))
282
309
  else
283
310
  STDERR.puts "ERROR: #{file} is an unknown file type, please use a file ending with '.rb', '.json' or '.yml'."
@@ -291,9 +318,9 @@ module Spiceweasel
291
318
  STDERR.puts e.message
292
319
  STDERR.puts "ERROR: Parsing error in #{file}."
293
320
  exit(-1)
294
- rescue Exception => e
295
- STDERR.puts "ERROR: Invalid or missing manifest .json, .rb, or .yml file provided."
296
- if(Spiceweasel::Config[:log_level].to_s == 'debug')
321
+ rescue Exception => e # rubocop:disable RescueException
322
+ STDERR.puts 'ERROR: Invalid or missing manifest .json, .rb, or .yml file provided.'
323
+ if Spiceweasel::Config[:log_level].to_s == 'debug'
297
324
  STDERR.puts "ERROR: #{e}\n#{e.backtrace.join("\n")}"
298
325
  end
299
326
  exit(-1)
@@ -302,17 +329,33 @@ module Spiceweasel
302
329
  end
303
330
 
304
331
  # find the .rb/.json/.yml file from the ARGV that isn't the clusterfile
305
- def get_manifest()
332
+ def find_manifest
306
333
  ARGV.each do |arg|
307
334
  if arg =~ /\.json$|\.rb$|\.yml$/
308
- unless ARGV[ARGV.find_index(arg)-1].eql?('--cluster-file')
309
- return arg
310
- end
335
+ return arg unless ARGV[ARGV.find_index(arg) - 1].eql?('--cluster-file')
336
+ end
337
+ end
338
+ end
339
+
340
+ # the --only options
341
+ def process_only(manifest)
342
+ only_list = Spiceweasel::Config[:only]
343
+ return manifest if only_list.empty?
344
+ only_list.each do |key|
345
+ unless MANIFEST_OPTIONS.member?(key)
346
+ STDERR.puts "ERROR: '--only #{key}' is an invalid option."
347
+ STDERR.puts "ERROR: Valid options are #{MANIFEST_OPTIONS}."
348
+ exit(-1)
311
349
  end
312
350
  end
351
+ only_list.push('berksfile') if only_list.member?('cookbooks')
352
+ only_list.push('data bags') if only_list.delete('data_bags')
353
+ manifest.keep_if { |key, val| only_list.member?(key) }
313
354
  end
314
355
 
315
356
  def process_manifest(manifest)
357
+ do_not_validate = Spiceweasel::Config[:novalidation]
358
+ berksfile = nil
316
359
  berksfile = Berksfile.new(manifest['berksfile']) if manifest.include?('berksfile')
317
360
  if berksfile
318
361
  cookbooks = Cookbooks.new(manifest['cookbooks'], berksfile.cookbook_list)
@@ -326,9 +369,11 @@ module Spiceweasel
326
369
  environments = Environments.new(manifest['environments'], cookbooks)
327
370
  roles = Roles.new(manifest['roles'], environments, cookbooks)
328
371
  data_bags = DataBags.new(manifest['data bags'])
329
- knifecommands = get_knife_commands() unless Spiceweasel::Config[:novalidation]
330
- nodes = Nodes.new(manifest['nodes'], cookbooks, environments, roles, knifecommands)
331
- clusters = Clusters.new(manifest['clusters'], cookbooks, environments, roles, knifecommands)
372
+ knifecommands = nil
373
+ knifecommands = find_knife_commands unless do_not_validate
374
+ options = manifest['options']
375
+ nodes = Nodes.new(manifest['nodes'], cookbooks, environments, roles, knifecommands, options)
376
+ clusters = Clusters.new(manifest['clusters'], cookbooks, environments, roles, knifecommands, options)
332
377
  knife = Knife.new(manifest['knife'], knifecommands)
333
378
 
334
379
  create += environments.create + roles.create + data_bags.create + nodes.create + clusters.create + knife.create
@@ -339,15 +384,15 @@ module Spiceweasel
339
384
  create = nodes.create + clusters.create
340
385
  delete = []
341
386
  end
342
- return create, delete
387
+ [create, delete]
343
388
  end
344
389
 
345
- def get_knife_commands()
390
+ def find_knife_commands
346
391
  require 'mixlib/shellout'
347
392
  allknifes = Mixlib::ShellOut.new('knife -h').run_command.stdout.split(/\n/)
348
- allknifes.keep_if {|x| x.start_with?('knife')}
393
+ allknifes.keep_if { |x| x.start_with?('knife') }
349
394
  Spiceweasel::Log.debug(allknifes)
350
- return allknifes
395
+ allknifes
351
396
  end
352
397
  end
353
398
  end