knife-solo 0.3.0.pre2 → 0.3.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG.md +70 -27
  2. data/README.rdoc +11 -6
  3. data/Rakefile +4 -2
  4. data/lib/chef/knife/bootstrap_solo.rb +40 -0
  5. data/lib/chef/knife/solo_bootstrap.rb +1 -1
  6. data/lib/chef/knife/solo_clean.rb +16 -4
  7. data/lib/chef/knife/solo_cook.rb +111 -36
  8. data/lib/chef/knife/solo_init.rb +14 -0
  9. data/lib/chef/knife/solo_prepare.rb +1 -1
  10. data/lib/knife-solo/bootstraps.rb +0 -18
  11. data/lib/knife-solo/bootstraps/darwin.rb +4 -16
  12. data/lib/knife-solo/bootstraps/linux.rb +36 -48
  13. data/lib/knife-solo/info.rb +1 -1
  14. data/lib/knife-solo/resources/knife.rb +4 -0
  15. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/.travis.yml +7 -0
  16. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/CHANGELOG +16 -0
  17. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/LICENSE +202 -0
  18. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/NOTICE +18 -0
  19. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/README.md +141 -0
  20. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search.rb +72 -0
  21. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search/overrides.rb +99 -0
  22. data/lib/{chef/knife/patches → knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/search}/parser.rb +1 -2
  23. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/lucene.treetop +150 -0
  24. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/lucene_nodes.rb +285 -0
  25. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/libraries/vendor/chef/solr_query/query_transform.rb +65 -0
  26. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/metadata.rb +11 -0
  27. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/recipes/default.rb +2 -0
  28. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/Gemfile +8 -0
  29. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/alpha.json +10 -0
  30. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/beta.json +10 -0
  31. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/node/without_json_class.json +7 -0
  32. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/jerry.json +8 -0
  33. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/lea.json +10 -0
  34. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/mike.json +13 -0
  35. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/data/data_bags/users/tom.json +10 -0
  36. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/test_data_bags.rb +44 -0
  37. data/lib/knife-solo/resources/patch_cookbooks/chef-solo-search/tests/test_search.rb +241 -0
  38. data/lib/knife-solo/resources/solo.rb.erb +10 -0
  39. data/lib/knife-solo/ssh_command.rb +4 -3
  40. data/lib/knife-solo/tools.rb +22 -0
  41. data/test/bootstraps_test.rb +4 -11
  42. data/test/integration/cases/encrypted_data_bag.rb +3 -0
  43. data/test/integration/cases/knife_bootstrap.rb +14 -0
  44. data/test/integration/debian6_bootstrap_test.rb +1 -1
  45. data/test/integration/{debian7_bootstrap_test.rb → debian7_knife_bootstrap_test.rb} +3 -3
  46. data/test/knife_bootstrap_test.rb +61 -0
  47. data/test/solo_cook_test.rb +78 -3
  48. data/test/support/integration_test.rb +8 -3
  49. data/test/tools_test.rb +82 -0
  50. metadata +63 -21
  51. data/lib/chef/knife/patches/search.rb +0 -110
  52. data/lib/knife-solo/config.rb +0 -39
  53. data/lib/knife-solo/resources/solo.rb +0 -6
  54. data/test/knife-solo/config_test.rb +0 -38
@@ -0,0 +1,44 @@
1
+ #
2
+ # Copyright 2011, edelight GmbH
3
+ #
4
+ # Authors:
5
+ # Markus Korn <markus.korn@edelight.de>
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require "test/unit"
21
+ require "chef"
22
+
23
+ # mocking chef such that it thinks it's running as chef-solo and knows about
24
+ # the location of the data_bag
25
+ Chef::Config[:solo] = true
26
+ Chef::Config[:data_bag_path] = "tests/data/data_bags"
27
+
28
+ def data_bag_item(bag, item)
29
+ # wrapper around creating a new Recipe instance and calling data_bag on it
30
+ node = Chef::Node.new()
31
+ cookbooks = Chef::CookbookCollection.new()
32
+ run_context = Chef::RunContext.new(node, cookbooks)
33
+ return Chef::Recipe.new("test_cookbook", "test_recipe", run_context).data_bag_item(bag, item)
34
+ end
35
+
36
+ class TestDataBags < Test::Unit::TestCase
37
+
38
+ def test_data_bag
39
+ item = data_bag_item("users", "mike")
40
+ assert_equal item["age"], 42
41
+ assert_equal item[:age], nil #upstream code for chef-solo does not use mashes
42
+ end
43
+
44
+ end
@@ -0,0 +1,241 @@
1
+ #
2
+ # Copyright 2011, edelight GmbH
3
+ #
4
+ # Authors:
5
+ # Markus Korn <markus.korn@edelight.de>
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require "test/unit"
21
+ require "chef"
22
+
23
+ # mocking chef such that it thinks it's running as chef-solo and knows about
24
+ # the location of the data_bag
25
+ Chef::Config[:solo] = true
26
+ Chef::Config[:data_bag_path] = "#{File.dirname(__FILE__)}/data/data_bags"
27
+
28
+ # load the extension
29
+ require File.expand_path('../../libraries/search', __FILE__)
30
+
31
+ module SearchDbTests
32
+
33
+ def test_search_all
34
+ # try to get data of all users
35
+ nodes = search(:users, "*:*")
36
+ assert_equal nodes.length, 4
37
+ nodes = search(:users)
38
+ assert_equal nodes.length, 4
39
+ nodes = search(:users, nil)
40
+ assert_equal nodes.length, 4
41
+ end
42
+
43
+ def test_search_exact_match
44
+ nodes = search(:users, "username:speedy")
45
+ assert_equal nodes.length, 1
46
+ assert_equal nodes[0]["username"], "speedy"
47
+ end
48
+
49
+ def test_get_all_with_field
50
+ nodes = search(:users, "username:*")
51
+ assert nodes.length > 0
52
+ assert nodes.all?{|x| !x["username"].nil?}
53
+ end
54
+
55
+ def test_get_all_without_field
56
+ nodes = search(:users, "(NOT username:*)")
57
+ assert nodes.length == 0
58
+ nodes = search(:users, "(NOT color:*)")
59
+ assert nodes.length == 3
60
+ assert nodes.all?{|x| x["color"].nil?}
61
+ end
62
+
63
+ def test_get_all_but_speedy
64
+ nodes = search(:users, "NOT username:speedy")
65
+ assert nodes.length > 0
66
+ assert nodes.all?{|x| x["username"] != "speedy"}
67
+ end
68
+
69
+ def test_array_includes
70
+ nodes = search(:users, "children:tom")
71
+ assert nodes.length == 2
72
+ assert nodes.all?{ |x| x["children"].include?("tom") }
73
+ nodes = search(:users, "children:jerry")
74
+ assert nodes.length == 1
75
+ assert nodes.all?{ |x| x["children"].include?("jerry") }
76
+ end
77
+
78
+ def test_boolean
79
+ nodes = search(:users, "married:true")
80
+ assert nodes.length == 3
81
+ assert nodes.all?{ |x| x["married"] == true }
82
+ nodes = search(:users, "married:false")
83
+ assert nodes.length == 1
84
+ assert nodes[0]["married"] == false
85
+ end
86
+
87
+ def test_integer
88
+ nodes = search(:users, "age:35")
89
+ assert nodes.length == 1
90
+ assert nodes[0]["age"] == 35
91
+ end
92
+
93
+ def test_AND_condition
94
+ nodes = search(:users, "married:true AND age:35")
95
+ assert nodes.length == 1
96
+ assert nodes[0]["username"] == "lea"
97
+ end
98
+
99
+ def test_OR_condition
100
+ nodes = search(:users, "age:42 OR age:22")
101
+ assert nodes.length == 2
102
+ end
103
+
104
+ def test_NOT_condition
105
+ nodes = search(:users, "children:tom AND (NOT gender:female)")
106
+ assert nodes.length == 1
107
+ nodes = search(:users, "children:tom AND (NOT gender:female) AND age:42")
108
+ assert nodes.length == 1
109
+ nodes = search(:users, "children:tom AND (NOT gender:female) AND (NOT age:42)")
110
+ assert nodes.length == 0
111
+ end
112
+
113
+ def test_any_value
114
+ nodes = search(:users, "children:*")
115
+ assert nodes.length == 2
116
+ end
117
+
118
+ def test_any_value_lucene_range
119
+ nodes = search(:users, "address:[* TO *]")
120
+ assert nodes.length == 2
121
+ end
122
+
123
+ def test_general_lucene_range_fails
124
+ assert_raises RuntimeError do
125
+ nodes = search(:users, "children:[aaa TO zzz]")
126
+ end
127
+ end
128
+
129
+ def test_block_usage
130
+ # bracket syntax
131
+ result = []
132
+ search(:users, "*:*") {|x| result << x["id"]}
133
+ assert result.length == 4
134
+
135
+ # do...end syntax
136
+ result = []
137
+ search(:users) do |x|
138
+ result << x["id"]
139
+ end
140
+ assert result.length == 4
141
+ end
142
+
143
+ def test_check_escaped_chars
144
+ nodes = search(:users, 'tag:tag\:\:test')
145
+ assert nodes.length == 1
146
+ nodes = search(:users, "tag:tag\\:\\:test")
147
+ assert nodes.length == 1
148
+ nodes = search(:users, 'tags:tag\:\:first')
149
+ assert nodes.length == 1
150
+ nodes = search(:users, "tags:tag\\:\\:first")
151
+ assert nodes.length == 1
152
+ nodes = search(:users, 'tags:tag\:\:*')
153
+ assert nodes.length == 1
154
+ nodes = search(:users, "tags:tag\\:\\:*")
155
+ assert nodes.length == 1
156
+ end
157
+
158
+ def test_wildcards
159
+ nodes = search(:users, "gender:f??ale")
160
+ assert nodes.length == 1
161
+ nodes = search(:users, "username:spee?y")
162
+ assert nodes.length == 1
163
+ nodes = search(:users, "username:spee*")
164
+ assert nodes.length == 1
165
+ end
166
+
167
+ def test_empty_field_value
168
+ assert_raise(RuntimeError) {
169
+ search(:users, "gender:#{nil} AND age:35")
170
+ }
171
+ assert_raise(RuntimeError) {
172
+ search(:users, "gender: AND age:35")
173
+ }
174
+ assert_raise(RuntimeError) {
175
+ search(:users, "gender:\"\" AND age:35")
176
+ }
177
+ end
178
+
179
+ def test_OR_group
180
+ nodes = search(:users, "id:(mike OR tom)")
181
+ assert nodes.length == 2
182
+ end
183
+
184
+ def test_nested_fieldnames
185
+ nodes = search(:users, "address_street:wilhelmsstrasse")
186
+ assert nodes.length == 1
187
+ nodes = search(:users, "address_street_floor:1")
188
+ assert nodes.length == 1
189
+ end
190
+ end
191
+
192
+ module SearchNodeTests
193
+ def test_list_nodes
194
+ nodes = search(:node)
195
+ assert_equal Chef::Node, nodes.first.class
196
+ assert_equal 3, nodes.length
197
+ end
198
+
199
+ def test_search_node_with_wide_filter
200
+ nodes = search(:node, "role:test_server AND chef_environment:default")
201
+ assert_equal 2, nodes.length
202
+ end
203
+
204
+ def test_search_node_with_narrow_filter
205
+ nodes = search(:node, "role:beta_server")
206
+ assert_equal 1, nodes.length
207
+ end
208
+
209
+ def test_search_node_with_attr_filter
210
+ nodes = search(:node, "hostname:beta.example.com")
211
+ assert_equal 1, nodes.length
212
+ end
213
+
214
+ def test_search_node_without_json_class
215
+ nodes = search(:node, "chef_environment:default")
216
+ assert_equal 3, nodes.length
217
+ end
218
+ end
219
+
220
+ class TestImplicitSearchDB < Test::Unit::TestCase
221
+ include SearchDbTests
222
+ include SearchNodeTests
223
+
224
+ def search(*args, &block)
225
+ # wrapper around creating a new Recipe instance and calling search on it
226
+ node = Chef::Node.new()
227
+ cookbooks = Chef::CookbookCollection.new()
228
+ run_context = Chef::RunContext.new(node, cookbooks, nil)
229
+ return Chef::Recipe.new("test_cookbook", "test_recipe", run_context).search(*args, &block)
230
+ end
231
+ end
232
+
233
+ class TestExplicitSearchDB < Test::Unit::TestCase
234
+ include SearchDbTests
235
+ include SearchNodeTests
236
+
237
+ def search(*args, &block)
238
+ Chef::Search::Query.new.search(*args, &block)
239
+ end
240
+ end
241
+
@@ -0,0 +1,10 @@
1
+ base = File.expand_path('..', __FILE__)
2
+
3
+ role_path File.join(base, 'roles')
4
+ data_bag_path File.join(base, 'data_bags')
5
+ encrypted_data_bag_secret File.join(base, 'data_bag_key')
6
+
7
+ cookbook_path []
8
+ <% cookbook_paths.each_with_index do |path, i| -%>
9
+ cookbook_path << File.join(base, 'cookbooks-<%= i+1 %>') # <%= path %>
10
+ <% end -%>
@@ -257,12 +257,13 @@ module KnifeSolo
257
257
  # TODO:
258
258
  # - move this to a dedicated "portability" module?
259
259
  # - use ruby in all cases instead?
260
- def run_portable_mkdir_p(folder)
260
+ def run_portable_mkdir_p(folder, mode = nil)
261
261
  if windows_node?
262
262
  # no mkdir -p on windows - fake it
263
- run_command %Q{ruby -e "require 'fileutils'; FileUtils.mkdir_p('#{folder}')"}
263
+ run_command %Q{ruby -e "require 'fileutils'; FileUtils.mkdir_p('#{folder}', :mode => #{mode})"}
264
264
  else
265
- run_command "mkdir -p #{folder}"
265
+ mode_option = (mode.nil? ? "" : "-m #{mode}")
266
+ run_command "mkdir -p #{mode_option} #{folder}"
266
267
  end
267
268
  end
268
269
 
@@ -7,5 +7,27 @@ module KnifeSolo
7
7
  def windows_client?
8
8
  RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
9
9
  end
10
+
11
+ def config_value(key, default = nil)
12
+ Tools.config_value(config, key, default)
13
+ end
14
+
15
+ # Chef 10 compatible way of getting correct precedence for command line
16
+ # and configuration file options. Adds correct handling of `false` values
17
+ # to the original example in
18
+ # http://docs.opscode.com/breaking_changes_chef_11.html#knife-configuration-parameter-changes
19
+ def self.config_value(config, key, default = nil)
20
+ key = key.to_sym
21
+ if !config[key].nil?
22
+ config[key]
23
+ elsif !Chef::Config[:knife][key].nil?
24
+ # when Chef 10 support is dropped, this branch can be removed
25
+ # as Chef 11 automatically merges the values to the `config` hash
26
+ Chef::Config[:knife][key]
27
+ else
28
+ default
29
+ end
30
+ end
31
+
10
32
  end
11
33
  end
@@ -6,7 +6,10 @@ class KnifeSolo::Bootstraps::StubOS < KnifeSolo::Bootstraps::Base
6
6
  end
7
7
 
8
8
  class KnifeSolo::Bootstraps::StubOS2 < KnifeSolo::Bootstraps::Base
9
- def distro ; {:type => 'gem', :version => 'Fanny Faker'} ; end
9
+ def distro
10
+ {:type => 'gem'}
11
+ end
12
+
10
13
  def gem_install
11
14
  # dont' actually install anything
12
15
  end
@@ -43,16 +46,6 @@ class BootstrapsTest < TestCase
43
46
  assert_equal prepare, bootstrap.prepare
44
47
  end
45
48
 
46
- def test_darwin_checks_for_xcode_install_and_barfs_if_missing
47
- bootstrap = KnifeSolo::Bootstraps::Darwin.new(mock)
48
- bootstrap.stubs(:gem_install)
49
- bootstrap.expects(:has_xcode_installed?).returns(false)
50
-
51
- assert_raises RuntimeError do
52
- bootstrap.bootstrap!
53
- end
54
- end
55
-
56
49
  def test_omnibus_install_methdod
57
50
  bootstrap = bootstrap_instance
58
51
  bootstrap.stubs(:distro).returns({:type => "omnibus"})
@@ -5,6 +5,9 @@ module EncryptedDataBag
5
5
  super
6
6
  FileUtils.cp $base_dir.join('support', 'data_bag_key'), 'data_bag_key'
7
7
  FileUtils.cp_r $base_dir.join('support', 'secret_cookbook'), 'cookbooks/secret_cookbook'
8
+ File.open('.chef/knife.rb', 'a') do |f|
9
+ f.puts 'encrypted_data_bag_secret "data_bag_key"'
10
+ end
8
11
  @password = "essential particles busy loud"
9
12
  create_data_bag
10
13
  end
@@ -0,0 +1,14 @@
1
+ # Tries to bootstrap with apache2 cookbook and
2
+ # verifies the "It Works!" page is present.
3
+
4
+ require $base_dir.join('integration', 'cases', 'apache2_cook')
5
+
6
+ module KnifeBootstrap
7
+ include Apache2Cook
8
+
9
+ def test_apache2
10
+ write_cheffile
11
+ assert_knife_command "bootstrap --solo --run-list=recipe[apache2]"
12
+ assert_match default_apache_message, http_response
13
+ end
14
+ end
@@ -6,7 +6,7 @@ class Debian6BootstrapTest < IntegrationTest
6
6
  end
7
7
 
8
8
  def image_id
9
- "ami-4d20a724"
9
+ "ami-7ce17315"
10
10
  end
11
11
 
12
12
  def prepare_server
@@ -1,6 +1,6 @@
1
1
  require 'integration_helper'
2
2
 
3
- class Debian7BootstrapTest < IntegrationTest
3
+ class Debian7KnifeBootstrapTest < IntegrationTest
4
4
  def user
5
5
  "admin"
6
6
  end
@@ -10,12 +10,12 @@ class Debian7BootstrapTest < IntegrationTest
10
10
  end
11
11
 
12
12
  def prepare_server
13
- # Do nothing as `solo bootstrap` will do everything
13
+ # Do nothing as `knife bootstrap --solo` will do everything
14
14
  end
15
15
 
16
16
  def default_apache_message
17
17
  /It works!/
18
18
  end
19
19
 
20
- include Apache2Bootstrap
20
+ include KnifeBootstrap
21
21
  end
@@ -0,0 +1,61 @@
1
+ require 'test_helper'
2
+ require 'support/kitchen_helper'
3
+
4
+ require 'chef/knife/bootstrap_solo'
5
+ require 'chef/knife/solo_bootstrap'
6
+
7
+ class KnifeBootstrapTest < TestCase
8
+ include KitchenHelper
9
+
10
+ def test_includes_solo_options
11
+ assert Chef::Knife::Bootstrap.options.include?(:solo)
12
+ end
13
+
14
+ def test_runs_solo_bootstrap_if_specified_as_option
15
+ Chef::Config.knife[:solo] = false
16
+ Chef::Knife::SoloBootstrap.any_instance.expects(:run)
17
+ Chef::Knife::Bootstrap.any_instance.expects(:run_with_chef_client).never
18
+ in_kitchen do
19
+ command("somehost", "--solo").run
20
+ end
21
+ end
22
+
23
+ def test_runs_solo_bootstrap_if_specified_as_chef_configuration
24
+ Chef::Config.knife[:solo] = true
25
+ Chef::Knife::SoloBootstrap.any_instance.expects(:run)
26
+ Chef::Knife::Bootstrap.any_instance.expects(:run_with_chef_client).never
27
+ in_kitchen do
28
+ command("somehost").run
29
+ end
30
+ end
31
+
32
+ def test_runs_original_bootstrap_by_default
33
+ Chef::Config.knife[:solo] = false
34
+ Chef::Knife::SoloBootstrap.any_instance.expects(:run).never
35
+ Chef::Knife::Bootstrap.any_instance.expects(:run_with_chef_client)
36
+ in_kitchen do
37
+ command("somehost").run
38
+ end
39
+ end
40
+
41
+ def test_runs_original_bootstrap_if_specified_as_option
42
+ Chef::Config.knife[:solo] = true
43
+ Chef::Knife::SoloBootstrap.any_instance.expects(:run).never
44
+ Chef::Knife::Bootstrap.any_instance.expects(:run_with_chef_client)
45
+ in_kitchen do
46
+ command("somehost", "--no-solo").run
47
+ end
48
+ end
49
+
50
+ def test_barks_without_atleast_a_hostname
51
+ cmd = command("--solo")
52
+ cmd.ui.expects(:err)
53
+ in_kitchen do
54
+ assert_exits cmd
55
+ end
56
+ end
57
+
58
+ def command(*args)
59
+ knife_command(Chef::Knife::Bootstrap, *args)
60
+ end
61
+ end