knife-solo 0.2.0 → 0.3.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # 0.3.0: _In progress_
2
+
1
3
  # 0.2.0: February 12, 2013
2
4
 
3
5
  ## Changes and new features
@@ -16,6 +18,7 @@
16
18
  * Drop support for Debian 5.0 Lenny (#172)
17
19
  * Integration tests for Debian 6 and 7 (74c6ed1 - f299a6)
18
20
  * Travis tests for both Chef 10 and 11 (#183)
21
+ * Remove solo.rb and transfer cookbooks to user-owned path (#1, #86, #125, #128, #177). See https://github.com/matschaffer/knife-solo/wiki/Upgrading-to-0.2.0
19
22
 
20
23
  ## Fixes
21
24
 
@@ -2,13 +2,11 @@ require 'chef/knife'
2
2
  require 'chef/knife/solo_cook'
3
3
  require 'chef/knife/solo_prepare'
4
4
 
5
- require 'knife-solo/kitchen_command'
6
5
  require 'knife-solo/ssh_command'
7
6
 
8
7
  class Chef
9
8
  class Knife
10
9
  class SoloBootstrap < Knife
11
- include KnifeSolo::KitchenCommand
12
10
  include KnifeSolo::SshCommand
13
11
 
14
12
  deps do
@@ -36,7 +34,6 @@ class Chef
36
34
 
37
35
  def validate!
38
36
  validate_ssh_options!
39
- validate_kitchen!
40
37
  end
41
38
 
42
39
  def command_with_same_args(klass)
@@ -1,24 +1,24 @@
1
1
  require 'chef/knife'
2
+
2
3
  require 'knife-solo/ssh_command'
3
- require 'knife-solo/kitchen_command'
4
+ require 'knife-solo/config'
4
5
 
5
6
  class Chef
6
7
  class Knife
7
8
  class SoloClean < Knife
8
9
  include KnifeSolo::SshCommand
9
- include KnifeSolo::KitchenCommand
10
10
 
11
11
  banner "knife solo clean [USER@]HOSTNAME"
12
12
 
13
13
  def run
14
+ @solo_config = KnifeSolo::Config.new
14
15
  validate!
15
- Chef::Config.from_file('solo.rb')
16
- run_command "rm -rf #{Chef::Config.file_cache_path}"
16
+ run_command "rm -rf #{@solo_config.chef_path}"
17
17
  end
18
18
 
19
19
  def validate!
20
20
  validate_ssh_options!
21
- validate_kitchen!
21
+ @solo_config.validate!
22
22
  end
23
23
  end
24
24
  end
@@ -1,9 +1,10 @@
1
1
  require 'chef/knife'
2
2
 
3
+ require 'knife-solo'
3
4
  require 'knife-solo/ssh_command'
4
- require 'knife-solo/kitchen_command'
5
5
  require 'knife-solo/node_config_command'
6
6
  require 'knife-solo/tools'
7
+ require 'knife-solo/config'
7
8
 
8
9
  class Chef
9
10
  class Knife
@@ -13,7 +14,6 @@ class Chef
13
14
  CHEF_VERSION_CONSTRAINT = ">=0.10.4" unless defined? CHEF_VERSION_CONSTRAINT
14
15
 
15
16
  include KnifeSolo::SshCommand
16
- include KnifeSolo::KitchenCommand
17
17
  include KnifeSolo::NodeConfigCommand
18
18
  include KnifeSolo::Tools
19
19
 
@@ -52,6 +52,8 @@ class Chef
52
52
  :description => 'Enable whyrun mode'
53
53
 
54
54
  def run
55
+ @solo_config = KnifeSolo::Config.new
56
+
55
57
  time('Run') do
56
58
  if config[:skip_chef_check]
57
59
  ui.warn '`--skip-chef-check` is deprecated, please use `--no-chef-check`.'
@@ -59,53 +61,35 @@ class Chef
59
61
  end
60
62
 
61
63
  validate!
62
- Chef::Config.from_file('solo.rb')
63
64
  check_chef_version if config[:chef_check]
64
65
  generate_node_config
65
66
  librarian_install if config[:librarian]
66
67
  rsync_kitchen
67
68
  add_patches
69
+ add_solo_config unless using_custom_solorb?
68
70
  cook unless config[:sync_only]
69
71
  end
70
72
  end
71
73
 
74
+ def_delegators :@solo_config,
75
+ :chef_path,
76
+ :using_custom_solorb?,
77
+ :patch_path
78
+
72
79
  def validate!
73
80
  validate_ssh_options!
74
- validate_kitchen!
75
- end
76
-
77
- def chef_path
78
- Chef::Config.file_cache_path
81
+ @solo_config.validate!
79
82
  end
80
83
 
81
84
  def chefignore
82
85
  @chefignore ||= ::Chef::Cookbook::Chefignore.new("./")
83
86
  end
84
87
 
85
- # cygwin rsync path must be adjusted to work
86
- def adjust_rsync_path(path)
87
- path.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
88
- end
89
-
90
- def adjust_rsync_path_on_node(path)
91
- return path unless windows_node?
92
- adjust_rsync_path(path)
93
- end
94
-
95
- def adjust_rsync_path_on_client(path)
96
- return path unless windows_client?
97
- adjust_rsync_path(path)
98
- end
99
-
100
88
  # see http://stackoverflow.com/questions/5798807/rsync-permission-denied-created-directories-have-no-permissions
101
89
  def rsync_permissions
102
90
  '--chmod=ugo=rwX' if windows_client?
103
91
  end
104
92
 
105
- def patch_path
106
- Array(Chef::Config.cookbook_path).first + "/chef_solo_patches/libraries"
107
- end
108
-
109
93
  def rsync_excludes
110
94
  (%w{revision-deploys tmp '.*'} + chefignore.ignores).uniq
111
95
  end
@@ -149,8 +133,12 @@ class Chef
149
133
  end
150
134
  end
151
135
 
136
+ def add_solo_config
137
+ rsync(KnifeSolo.resource('solo.rb'), chef_path)
138
+ end
139
+
152
140
  def rsync(source_path, target_path, extra_opts = '')
153
- cmd = %Q{rsync -rl #{rsync_permissions} --rsh="ssh #{ssh_args}" #{extra_opts} #{rsync_excludes.collect{ |ignore| "--exclude #{ignore} " }.join} #{adjust_rsync_path_on_client(source_path)} :#{adjust_rsync_path_on_node(target_path)}}
141
+ cmd = %Q|rsync -rl #{rsync_permissions} --rsh="ssh #{ssh_args}" #{extra_opts} #{rsync_excludes.collect{ |ignore| "--exclude #{ignore} " }.join} #{source_path} :#{target_path}|
154
142
  ui.msg cmd if debug?
155
143
  system! cmd
156
144
  end
@@ -26,7 +26,6 @@ class Chef
26
26
  create_kitchen
27
27
  create_cupboards %w[nodes roles data_bags site-cookbooks cookbooks]
28
28
  librarian_init if config[:librarian]
29
- create_solo_config
30
29
  end
31
30
 
32
31
  def validate!
@@ -51,22 +50,6 @@ class Chef
51
50
  mkdir @base unless @base == '.'
52
51
  end
53
52
 
54
- def create_solo_config
55
- solo_file = File.join(@base, 'solo.rb')
56
- return if File.exist? solo_file
57
-
58
- File.open(solo_file, 'w') do |f|
59
- f << <<-RUBY.gsub(/^ {12}/, '')
60
- file_cache_path "/tmp/chef-solo"
61
- data_bag_path "/tmp/chef-solo/data_bags"
62
- encrypted_data_bag_secret "/tmp/chef-solo/data_bag_key"
63
- cookbook_path [ "/tmp/chef-solo/site-cookbooks",
64
- "/tmp/chef-solo/cookbooks" ]
65
- role_path "/tmp/chef-solo/roles"
66
- RUBY
67
- end
68
- end
69
-
70
53
  def librarian_init
71
54
  cheffile = File.join(@base, 'Cheffile')
72
55
  unless File.exist?(cheffile)
@@ -1,6 +1,5 @@
1
1
  require 'chef/knife'
2
2
  require 'knife-solo/ssh_command'
3
- require 'knife-solo/kitchen_command'
4
3
  require 'knife-solo/node_config_command'
5
4
 
6
5
  class Chef
@@ -9,7 +8,6 @@ class Chef
9
8
  # Copyright 2010, 2011, Miquel Torres <tobami@googlemail.com>
10
9
  class SoloPrepare < Knife
11
10
  include KnifeSolo::SshCommand
12
- include KnifeSolo::KitchenCommand
13
11
  include KnifeSolo::NodeConfigCommand
14
12
 
15
13
  deps do
@@ -44,7 +42,6 @@ class Chef
44
42
 
45
43
  def validate!
46
44
  validate_ssh_options!
47
- validate_kitchen!
48
45
  end
49
46
 
50
47
  def bootstrap
@@ -1 +1,7 @@
1
1
  require 'knife-solo/info'
2
+
3
+ module KnifeSolo
4
+ def self.resource(name)
5
+ Pathname.new(__FILE__).dirname.join('knife-solo/resources', name)
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ require 'chef/config'
2
+
3
+ module KnifeSolo
4
+ # Encapsulates some logic for checking and extracting
5
+ # path configuration from the structure of the
6
+ # current kitchen
7
+ class Config
8
+ def solo_path
9
+ Chef::Config.knife[:solo_path]
10
+ end
11
+
12
+ def chef_path
13
+ solo_path || './chef-solo'
14
+ end
15
+
16
+ def cookbook_path
17
+ if using_custom_solorb?
18
+ Chef::Config.from_file('solo.rb')
19
+ Array(Chef::Config.cookbook_path).first
20
+ else
21
+ chef_path + '/cookbooks'
22
+ end
23
+ end
24
+
25
+ def patch_path
26
+ cookbook_path + "/chef_solo_patches/libraries"
27
+ end
28
+
29
+ def using_custom_solorb?
30
+ File.exist?('solo.rb')
31
+ end
32
+
33
+ def validate!
34
+ raise Error, "You have a solo.rb file, but knife[:solo_path] is not set. You probably need to delete solo.rb unless you've customized it. See https://github.com/matschaffer/knife-solo/wiki/Upgrading-to-0.3.0 for more information." if using_custom_solorb? && solo_path.nil?
35
+ end
36
+
37
+ class Error < StandardError; end
38
+ end
39
+ end
@@ -1,6 +1,6 @@
1
1
  module KnifeSolo
2
2
  def self.version
3
- '0.2.0'
3
+ '0.3.0.pre1'
4
4
  end
5
5
 
6
6
  def self.post_install_message
@@ -0,0 +1,6 @@
1
+ base = File.expand_path('..', __FILE__)
2
+
3
+ data_bag_path base + '/data_bags'
4
+ encrypted_data_bag_secret base + '/data_bag_key'
5
+ role_path base + '/roles'
6
+ cookbook_path [ base + '/site-cookbooks', base + '/cookbooks' ]
@@ -0,0 +1,13 @@
1
+ module CachePathUsage
2
+ def setup
3
+ super
4
+ FileUtils.cp_r $base_dir.join('support', 'cache_using_cookbook'), 'cookbooks/cache_using_cookbook'
5
+ end
6
+
7
+ def test_changing_a_cached_directory_between_cooks
8
+ write_nodefile(run_count: 1, run_list: ["cache_using_cookbook"])
9
+ assert_subcommand "cook"
10
+ write_nodefile(run_count: 2, run_list: ["cache_using_cookbook"])
11
+ assert_subcommand "cook"
12
+ end
13
+ end
@@ -12,4 +12,5 @@ class Ubuntu12_04Test < IntegrationTest
12
12
  include EmptyCook
13
13
  include Apache2Cook
14
14
  include EncryptedDataBag
15
+ include CachePathUsage
15
16
  end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+ require 'knife-solo/config'
3
+
4
+ class KnifeSoloConfigTest < TestCase
5
+ def setup
6
+ super
7
+ @config = KnifeSolo::Config.new
8
+ end
9
+
10
+ def teardown
11
+ super
12
+ FileUtils.rm_f 'solo.rb'
13
+ end
14
+
15
+ def test_uses_cookbook_path_from_solo_rb_if_available
16
+ write_file('solo.rb', <<-RUBY)
17
+ knife[:solo_path] = "./custom"
18
+ cookbook_path ["./custom/path"]
19
+ RUBY
20
+ assert_equal "./custom/path", @config.cookbook_path
21
+ end
22
+
23
+ def test_reads_chef_root_path_from_knife_config_or_defaults_to_home
24
+ assert_equal './chef-solo', @config.chef_path
25
+ Chef::Config.knife[:solo_path] = "/tmp/custom-chef-solo"
26
+ assert_equal "/tmp/custom-chef-solo", @config.chef_path
27
+ end
28
+
29
+ def test_fails_validation_if_user_has_solo_rb_and_no_solo_path
30
+ Chef::Config.knife[:solo_path] = nil
31
+ write_file('solo.rb', <<-RUBY)
32
+ cookbook_path ["custom/path"]
33
+ RUBY
34
+ assert_raises KnifeSolo::Config::Error do
35
+ @config.validate!
36
+ end
37
+ end
38
+ end
@@ -16,18 +16,6 @@ class SoloCookTest < TestCase
16
16
  include KitchenHelper
17
17
  include ValidationHelper::ValidationTests
18
18
 
19
- def test_gets_destination_path_from_chef_config
20
- cmd = command
21
- Chef::Config.file_cache_path "/foo/chef-solo"
22
- assert_equal "/foo/chef-solo", cmd.chef_path
23
- end
24
-
25
- def test_gets_patch_path_from_chef_config
26
- cmd = command
27
- Chef::Config.cookbook_path ["/bar/chef-solo/cookbooks"]
28
- assert_equal "/bar/chef-solo/cookbooks/chef_solo_patches/libraries", cmd.patch_path
29
- end
30
-
31
19
  def test_chefignore_is_valid_object
32
20
  assert_instance_of Chef::Cookbook::Chefignore, command.chefignore
33
21
  end
@@ -152,8 +140,8 @@ class SoloCookTest < TestCase
152
140
  def command(*args)
153
141
  cmd = knife_command(Chef::Knife::SoloCook, *args)
154
142
  cmd.stubs(:check_chef_version)
155
- cmd.stubs(:rsync_kitchen)
156
143
  cmd.stubs(:add_patches)
144
+ cmd.stubs(:rsync)
157
145
  cmd.stubs(:stream_command).returns(SuccessfulResult.new)
158
146
  cmd
159
147
  end
@@ -0,0 +1,7 @@
1
+ name 'cache_using_cookbook'
2
+ maintainer 'Mat Schaffer'
3
+ maintainer_email 'mat@schaffer.me'
4
+ license 'MIT'
5
+ description 'Writes some data to the cache path.'
6
+ long_description 'This helps ensure that we can do this multiple times regardless of what user initiates the run.'
7
+ version '0.1.0'
@@ -0,0 +1,33 @@
1
+ #
2
+ # Cookbook Name:: cache_using_cookbook
3
+ # Recipe:: default
4
+ #
5
+ # Copyright 2013, Mat Schaffer
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+
27
+ container = Chef::Config[:file_cache_path] + "/test_dir"
28
+
29
+ directory container
30
+
31
+ file container + "/test_file" do
32
+ content "This was generated from run #{node['run_count']}"
33
+ end
@@ -3,6 +3,11 @@ class TestCase < MiniTest::Unit::TestCase
3
3
  super unless self.class == TestCase
4
4
  end
5
5
 
6
+ def write_file(file, contents)
7
+ FileUtils.mkpath(File.dirname(file))
8
+ File.open(file, 'w') { |f| f.print contents }
9
+ end
10
+
6
11
  def knife_command(cmd_class, *args)
7
12
  cmd_class.load_deps
8
13
  command = cmd_class.new(args)
@@ -15,25 +15,7 @@ module ValidationHelper
15
15
  end
16
16
  end
17
17
 
18
- module KitchenCommandTests
19
- include KitchenHelper
20
-
21
- def test_barks_outside_of_the_kitchen
22
- cmd = default_command
23
- cmd.ui.expects(:err).with(regexp_matches(/must be run inside .* kitchen/))
24
- outside_kitchen do
25
- assert_exits cmd
26
- end
27
- end
28
-
29
- # Returns a Knife instance that shoud run without other validation errors.
30
- def default_command
31
- command("somehost")
32
- end
33
- end
34
-
35
18
  module ValidationTests
36
19
  include SshCommandTests
37
- include KitchenCommandTests
38
20
  end
39
21
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-solo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.3.0.pre1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mat Schaffer
@@ -204,11 +204,12 @@ files:
204
204
  - lib/knife-solo/bootstraps/freebsd.rb
205
205
  - lib/knife-solo/bootstraps/linux.rb
206
206
  - lib/knife-solo/bootstraps/sun_os.rb
207
+ - lib/knife-solo/config.rb
207
208
  - lib/knife-solo/deprecated_command.rb
208
209
  - lib/knife-solo/gitignore.rb
209
210
  - lib/knife-solo/info.rb
210
- - lib/knife-solo/kitchen_command.rb
211
211
  - lib/knife-solo/node_config_command.rb
212
+ - lib/knife-solo/resources/solo.rb
212
213
  - lib/knife-solo/ssh_command.rb
213
214
  - lib/knife-solo/tools.rb
214
215
  - test/bootstraps_test.rb
@@ -217,6 +218,7 @@ files:
217
218
  - test/integration/amazon_linux_2012_09_bootstrap_test.rb
218
219
  - test/integration/cases/apache2_bootstrap.rb
219
220
  - test/integration/cases/apache2_cook.rb
221
+ - test/integration/cases/cache_path_usage.rb
220
222
  - test/integration/cases/empty_cook.rb
221
223
  - test/integration/cases/encrypted_data_bag.rb
222
224
  - test/integration/centos5_6_test.rb
@@ -230,7 +232,7 @@ files:
230
232
  - test/integration/ubuntu12_04_bootstrap_test.rb
231
233
  - test/integration/ubuntu12_04_test.rb
232
234
  - test/integration_helper.rb
233
- - test/kitchen_command_test.rb
235
+ - test/knife-solo/config_test.rb
234
236
  - test/minitest/parallel.rb
235
237
  - test/node_config_command_test.rb
236
238
  - test/solo_bootstrap_test.rb
@@ -239,6 +241,8 @@ files:
239
241
  - test/solo_init_test.rb
240
242
  - test/solo_prepare_test.rb
241
243
  - test/ssh_command_test.rb
244
+ - test/support/cache_using_cookbook/metadata.rb
245
+ - test/support/cache_using_cookbook/recipes/default.rb
242
246
  - test/support/config.yml.example
243
247
  - test/support/data_bag_key
244
248
  - test/support/ec2_runner.rb
@@ -273,9 +277,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
273
277
  required_rubygems_version: !ruby/object:Gem::Requirement
274
278
  none: false
275
279
  requirements:
276
- - - ! '>='
280
+ - - ! '>'
277
281
  - !ruby/object:Gem::Version
278
- version: '0'
282
+ version: 1.3.1
279
283
  requirements: []
280
284
  rubyforge_project:
281
285
  rubygems_version: 1.8.24
@@ -289,6 +293,7 @@ test_files:
289
293
  - test/integration/amazon_linux_2012_09_bootstrap_test.rb
290
294
  - test/integration/cases/apache2_bootstrap.rb
291
295
  - test/integration/cases/apache2_cook.rb
296
+ - test/integration/cases/cache_path_usage.rb
292
297
  - test/integration/cases/empty_cook.rb
293
298
  - test/integration/cases/encrypted_data_bag.rb
294
299
  - test/integration/centos5_6_test.rb
@@ -302,7 +307,7 @@ test_files:
302
307
  - test/integration/ubuntu12_04_bootstrap_test.rb
303
308
  - test/integration/ubuntu12_04_test.rb
304
309
  - test/integration_helper.rb
305
- - test/kitchen_command_test.rb
310
+ - test/knife-solo/config_test.rb
306
311
  - test/minitest/parallel.rb
307
312
  - test/node_config_command_test.rb
308
313
  - test/solo_bootstrap_test.rb
@@ -311,6 +316,8 @@ test_files:
311
316
  - test/solo_init_test.rb
312
317
  - test/solo_prepare_test.rb
313
318
  - test/ssh_command_test.rb
319
+ - test/support/cache_using_cookbook/metadata.rb
320
+ - test/support/cache_using_cookbook/recipes/default.rb
314
321
  - test/support/config.yml.example
315
322
  - test/support/data_bag_key
316
323
  - test/support/ec2_runner.rb
@@ -1,26 +0,0 @@
1
- module KnifeSolo
2
- module KitchenCommand
3
- def self.required_files
4
- %w(solo.rb)
5
- end
6
-
7
- def validate_kitchen!
8
- unless required_files_present?
9
- ui.fatal "This command must be run inside a Chef solo kitchen."
10
- exit 1
11
- end
12
- end
13
-
14
- def required_files_present?
15
- KitchenCommand.required_files.inject(true) do |m, f|
16
- check = File.exists?(f)
17
- warn_for_required_file(f) unless check
18
- m && check
19
- end
20
- end
21
-
22
- def warn_for_required_file(file)
23
- ui.error "#{file} is a required file/directory"
24
- end
25
- end
26
- end
@@ -1,31 +0,0 @@
1
- require 'test_helper'
2
- require 'support/kitchen_helper'
3
-
4
- require 'chef/knife'
5
- require 'knife-solo/kitchen_command'
6
-
7
- class DummyKitchenCommand < Chef::Knife
8
- include KnifeSolo::KitchenCommand
9
- end
10
-
11
- class KitchenCommandTest < TestCase
12
- include KitchenHelper
13
-
14
- def test_barks_outside_of_the_kitchen
15
- cmd = command
16
- cmd.ui.expects(:err).with(regexp_matches(/must be run inside .* kitchen/))
17
- outside_kitchen do
18
- assert_exits { cmd.validate_kitchen! }
19
- end
20
- end
21
-
22
- def test_runs_when_in_a_kitchen
23
- in_kitchen do
24
- command.validate_kitchen!
25
- end
26
- end
27
-
28
- def command(*args)
29
- knife_command(DummyKitchenCommand, *args)
30
- end
31
- end