chef-dk 0.3.0 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/lib/chef-dk/cli.rb +7 -5
  4. data/lib/chef-dk/command/generate.rb +2 -0
  5. data/lib/chef-dk/command/generator_commands.rb +8 -0
  6. data/lib/chef-dk/command/generator_commands/base.rb +4 -1
  7. data/lib/chef-dk/command/generator_commands/policyfile.rb +83 -0
  8. data/lib/chef-dk/command/install.rb +4 -5
  9. data/lib/chef-dk/command/push.rb +4 -5
  10. data/lib/chef-dk/command/verify.rb +3 -2
  11. data/lib/chef-dk/component_test.rb +7 -2
  12. data/lib/chef-dk/exceptions.rb +3 -34
  13. data/lib/chef-dk/helpers.rb +20 -2
  14. data/lib/chef-dk/policyfile/cookbook_locks.rb +19 -1
  15. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +11 -1
  16. data/lib/chef-dk/policyfile/storage_config.rb +23 -0
  17. data/lib/chef-dk/policyfile/uploader.rb +1 -1
  18. data/lib/chef-dk/policyfile_services/install.rb +19 -32
  19. data/lib/chef-dk/policyfile_services/push.rb +17 -27
  20. data/lib/chef-dk/service_exception_inspectors.rb +25 -0
  21. data/lib/chef-dk/service_exception_inspectors/base.rb +40 -0
  22. data/lib/chef-dk/service_exception_inspectors/http.rb +121 -0
  23. data/lib/chef-dk/service_exceptions.rb +77 -0
  24. data/lib/chef-dk/skeletons/code_generator/recipes/policyfile.rb +8 -0
  25. data/lib/chef-dk/skeletons/code_generator/templates/default/Policyfile.rb.erb +16 -0
  26. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +1 -1
  27. data/lib/chef-dk/version.rb +1 -1
  28. data/spec/unit/cli_spec.rb +126 -65
  29. data/spec/unit/command/exec_spec.rb +7 -2
  30. data/spec/unit/command/generator_commands/cookbook_spec.rb +27 -1
  31. data/spec/unit/command/generator_commands/policyfile_spec.rb +125 -0
  32. data/spec/unit/command/install_spec.rb +3 -4
  33. data/spec/unit/command/push_spec.rb +6 -7
  34. data/spec/unit/command/shell_init_spec.rb +5 -1
  35. data/spec/unit/cookbook_profiler/git_spec.rb +2 -2
  36. data/spec/unit/policyfile/cookbook_locks_spec.rb +58 -0
  37. data/spec/unit/policyfile/read_cookbook_for_compat_mode_upload_spec.rb +8 -1
  38. data/spec/unit/policyfile/storage_config_spec.rb +75 -1
  39. data/spec/unit/policyfile/uploader_spec.rb +31 -0
  40. data/spec/unit/policyfile_lock_validation_spec.rb +13 -12
  41. data/spec/unit/policyfile_services/install_spec.rb +5 -3
  42. data/spec/unit/policyfile_services/push_spec.rb +7 -5
  43. data/spec/unit/service_exception_inspectors/base_spec.rb +43 -0
  44. data/spec/unit/service_exception_inspectors/http_spec.rb +140 -0
  45. metadata +41 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f843be984f4748b386cfc76d5b13fc53a015ffeb
4
- data.tar.gz: ff6284980c5d4db06395d5264fae6de79dd858f3
3
+ metadata.gz: 15ddf96556ab7bfa73a009627a4bee13f83bada0
4
+ data.tar.gz: c3f5519baae22cf7d471a49ed968ebebbc826ad1
5
5
  SHA512:
6
- metadata.gz: 2c7ebbe3baf7bae4ca25072f6f62da8ee3c6cf14aa38d4bf7af8632338bed6f3b9949c06ee0e7283b958b1a61e38178a9bec9bbf9f04b3e0ad672e1c18bf99bf
7
- data.tar.gz: 0d0c18793a5a724ba719d4237a3f8e58ae1a6ed9bb07020277df9c9ce96caac5ba5632728004d6e91caa2a080fc0b150ef32906a305c2326d697889d202a6fd7
6
+ metadata.gz: f4a7492bafe9715b38a62f86b9ce94ed15bd002663f87624989d36e8f9006f05c662b58fd7169fd3c7ce7ea199d53c86fa128451f5c7a95dad653db468f61c0c
7
+ data.tar.gz: 86a69277b0e3c9ce1c132c9abc6ed58a2d4d48fd7083247bb65427361afd52bc86bff1ec529fbe5e4244650cf789909c8725b85cc10b039ff0c0054dc6e4acec
data/README.md CHANGED
@@ -70,6 +70,11 @@ cookbook. Supports the `-s SOURCE` option similar to template.
70
70
  * `chef generate lwrp` Creates a new LWRP resource and provider in an
71
71
  existing cookbook.
72
72
 
73
+ The `chef generate` command also accepts additional `--generator-arg key=value`
74
+ pairs that can be used to supply ad-hoc data to a generator cookbook.
75
+ For example, you might specify `--generator-arg database=mysql` and then only
76
+ write a template for `recipes/mysql.rb` if `context.database == 'mysql'`.
77
+
73
78
  #### `chef gem`
74
79
  `chef gem` is a wrapper command that manages installation and updating
75
80
  of rubygems for the Ruby installation embedded in the ChefDK package.
data/lib/chef-dk/cli.rb CHANGED
@@ -141,7 +141,7 @@ BANNER
141
141
 
142
142
  # Find PATH or Path correctly if we are on Windows
143
143
  def path_key
144
- ENV.keys.grep(/\Apath\Z/i).first
144
+ env.keys.grep(/\Apath\Z/i).first
145
145
  end
146
146
 
147
147
  # upcase drive letters for comparison since ruby has a String#capitalize function
@@ -161,6 +161,8 @@ BANNER
161
161
  # when they have the embedded_bin_dir before the omnibus_bin_dir -- both of which will
162
162
  # defeat appbundler and interact very badly with our intent.
163
163
  def sanity_check!
164
+ # When installed outside of omnibus, trust the user to configure their PATH
165
+ return true unless omnibus_install?
164
166
  paths = env[path_key].split(File::PATH_SEPARATOR)
165
167
  paths.map! { |p| drive_upcase(Chef::Util::PathHelper.cleanpath(p)) }
166
168
  embed_index = paths.index(drive_upcase(Chef::Util::PathHelper.cleanpath(omnibus_embedded_bin_dir)))
@@ -168,12 +170,12 @@ BANNER
168
170
  if embed_index
169
171
  if bin_index
170
172
  if embed_index < bin_index
171
- msg("WARN: #{omnibus_embedded_bin_dir} is before #{omnibus_bin_dir} in your #{path_key}, please reverse that order.")
172
- msg("WARN: consider using the correct `chef shell-init <shell>` command to setup your environment correctly.")
173
+ err("WARN: #{omnibus_embedded_bin_dir} is before #{omnibus_bin_dir} in your #{path_key}, please reverse that order.")
174
+ err("WARN: consider using the correct `chef shell-init <shell>` command to setup your environment correctly.")
173
175
  end
174
176
  else
175
- msg("WARN: only #{omnibus_embedded_bin_dir} is present in your path, you must add #{omnibus_bin_dir} before that directory.")
176
- msg("WARN: consider using the correct `chef shell-init <shell>` command to setup your environment correctly.")
177
+ err("WARN: only #{omnibus_embedded_bin_dir} is present in your path, you must add #{omnibus_bin_dir} before that directory.")
178
+ err("WARN: consider using the correct `chef shell-init <shell>` command to setup your environment correctly.")
177
179
  end
178
180
  end
179
181
  end
@@ -27,6 +27,7 @@ require 'chef-dk/command/generator_commands/lwrp'
27
27
  require 'chef-dk/command/generator_commands/recipe'
28
28
  require 'chef-dk/command/generator_commands/template'
29
29
  require 'chef-dk/command/generator_commands/repo'
30
+ require 'chef-dk/command/generator_commands/policyfile'
30
31
 
31
32
  module ChefDK
32
33
  module Command
@@ -50,6 +51,7 @@ module ChefDK
50
51
  generator(:file, :CookbookFile, "Generate a cookbook file")
51
52
  generator(:lwrp, :LWRP, "Generate a lightweight resource/provider")
52
53
  generator(:repo, :Repo, "Generate a Chef policy repository")
54
+ generator(:policyfile, :Policyfile, "Generate a Policyfile for use with the install/push commands (experimental)")
53
55
 
54
56
  def self.banner_headline
55
57
  <<-E
@@ -58,6 +58,14 @@ module ChefDK
58
58
  :default => File.expand_path("../../skeletons", __FILE__),
59
59
  :proc => Proc.new { |s| File.expand_path(s) },
60
60
  :on => :tail
61
+
62
+ generator_args = [] # accumulator variable
63
+ option :generator_arg,
64
+ :short => "-a KEY=VALUE",
65
+ :long => "--generator-arg KEY=VALUE",
66
+ :description => "Use to set arbitrary attribute KEY to VALUE in the code_generator cookbook",
67
+ :default => [],
68
+ :proc => Proc.new { |s| generator_args << s.split("=").map(&:strip) }
61
69
  end
62
70
 
63
71
  # ## GeneratorCommands
@@ -60,6 +60,10 @@ module ChefDK
60
60
  config.each do |k,v|
61
61
  Generator.add_attr_to_context(k, v)
62
62
  end
63
+ # inject the arbitrary args supplied on cmdline, default = []
64
+ config[:generator_arg].each do |k,v|
65
+ Generator.add_attr_to_context(k, v)
66
+ end
63
67
  end
64
68
 
65
69
  # Checks the `PATH` for the presence of a `git` (or `git.exe`, on
@@ -73,4 +77,3 @@ module ChefDK
73
77
  end
74
78
  end
75
79
  end
76
-
@@ -0,0 +1,83 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef-dk/command/generator_commands/base'
19
+
20
+ module ChefDK
21
+ module Command
22
+ module GeneratorCommands
23
+
24
+ class Policyfile < Base
25
+
26
+ banner "Usage: chef generate policyfile [NAME] [options]"
27
+
28
+ options.merge!(SharedGeneratorOptions.options)
29
+
30
+ attr_reader :new_file_basename
31
+ attr_reader :policyfile_dir
32
+
33
+ def initialize(*args)
34
+ super
35
+ @params_valid = true
36
+ end
37
+
38
+ def recipe
39
+ 'policyfile'
40
+ end
41
+
42
+ def setup_context
43
+ super
44
+ Generator.add_attr_to_context(:policyfile_dir, policyfile_dir)
45
+ Generator.add_attr_to_context(:new_file_basename, new_file_basename)
46
+ end
47
+
48
+ def run
49
+ read_and_validate_params
50
+ if params_valid?
51
+ setup_context
52
+ chef_runner.converge
53
+ 0
54
+ else
55
+ msg(banner)
56
+ 1
57
+ end
58
+ end
59
+
60
+ def read_and_validate_params
61
+ arguments = parse_options(params)
62
+ new_file_path =
63
+ case arguments.size
64
+ when 0
65
+ "Policyfile"
66
+ when 1
67
+ arguments[0]
68
+ else
69
+ @params_valid = false
70
+ return false
71
+ end
72
+ @new_file_basename = File.basename(new_file_path, ".rb")
73
+ @policyfile_dir = File.expand_path(File.dirname(new_file_path))
74
+ end
75
+
76
+ def params_valid?
77
+ @params_valid
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end
@@ -80,12 +80,11 @@ E
80
80
 
81
81
  def handle_error(error)
82
82
  ui.err("Error: #{error.message}")
83
- if error.respond_to?(:cause) && error.cause
84
- cause = error.cause
85
- ui.err("Reason: #{cause.class.name}")
83
+ if error.respond_to?(:reason)
84
+ ui.err("Reason: #{error.reason}")
86
85
  ui.err("")
87
- ui.err(cause.message)
88
- ui.err(cause.backtrace.join("\n")) if debug?
86
+ ui.err(error.extended_error_info) if debug?
87
+ ui.err(error.cause.backtrace.join("\n")) if debug?
89
88
  end
90
89
  end
91
90
 
@@ -96,12 +96,11 @@ E
96
96
 
97
97
  def handle_error(error)
98
98
  ui.err("Error: #{error.message}")
99
- if error.respond_to?(:cause) && error.cause
100
- cause = error.cause
101
- ui.err("Reason: #{cause.class.name}")
99
+ if error.respond_to?(:reason)
100
+ ui.err("Reason: #{error.reason}")
102
101
  ui.err("")
103
- ui.err(cause.message)
104
- ui.err(cause.backtrace.join("\n")) if debug?
102
+ ui.err(error.extended_error_info) if debug?
103
+ ui.err(error.cause.backtrace.join("\n")) if debug?
105
104
  end
106
105
  end
107
106
 
@@ -23,6 +23,7 @@ module ChefDK
23
23
  module Command
24
24
  class Verify < ChefDK::Command::Base
25
25
 
26
+ include ChefDK::Helpers
26
27
 
27
28
  banner "Usage: chef verify [component, ...] [options]"
28
29
 
@@ -120,7 +121,7 @@ module ChefDK
120
121
  c.smoke_test do
121
122
  tmpdir do |cwd|
122
123
  FileUtils.mkdir(File.join(cwd, "spec"))
123
- File.open(File.join(cwd, "spec", "spec_helper.rb"), "w+") do |f|
124
+ with_file(File.join(cwd, "spec", "spec_helper.rb")) do |f|
124
125
  f.write <<-EOF
125
126
  require 'chefspec'
126
127
  require 'chefspec/berkshelf'
@@ -132,7 +133,7 @@ end
132
133
  EOF
133
134
  end
134
135
  FileUtils.touch(File.join(cwd, "Berksfile"))
135
- File.open(File.join(cwd, "spec", "foo_spec.rb"), "w+") do |f|
136
+ with_file(File.join(cwd, "spec", "foo_spec.rb")) do |f|
136
137
  f.write <<-EOF
137
138
  require 'spec_helper'
138
139
  EOF
@@ -131,7 +131,13 @@ module ChefDK
131
131
 
132
132
  def gem_base_dir
133
133
  return nil if @gem_name_for_base_dir.nil?
134
- Gem::Specification::find_by_name(@gem_name_for_base_dir).gem_dir
134
+ # There is no way to say "give me the latest prerelease OR normal version of this gem.
135
+ # So we first ask if there is a normal version, and if there is not, we ask if there
136
+ # is a prerelease version. ">= 0.a" is how we ask for a prerelease version, because a
137
+ # prerelease version is defined as "any version with a letter in it."
138
+ gem = Gem::Specification::find_by_name(@gem_name_for_base_dir)
139
+ gem ||= Gem::Specification::find_by_name(@gem_name_for_base_dir, '>= 0.a')
140
+ gem.gem_dir
135
141
  end
136
142
 
137
143
  def gem_base_dir=(gem_name)
@@ -152,4 +158,3 @@ module ChefDK
152
158
 
153
159
  end
154
160
  end
155
-
@@ -17,40 +17,6 @@
17
17
 
18
18
  module ChefDK
19
19
 
20
- # Base class for errors raised by ChefDK::PolicyfileServices objects. Don't
21
- # raise this directly, create a descriptively-named subclass. You can rescue
22
- # this to catch all errors from PolicyfileServices objects though.
23
- class PolicyfileServiceError < StandardError
24
- end
25
-
26
- class PolicyfileNotFound < PolicyfileServiceError
27
- end
28
-
29
- class LockfileNotFound < PolicyfileServiceError
30
- end
31
-
32
- class PolicyfileInstallError < PolicyfileServiceError
33
-
34
- attr_reader :cause
35
-
36
- def initialize(message, cause)
37
- super(message)
38
- @cause = cause
39
- end
40
-
41
- end
42
-
43
- class PolicyfilePushError < PolicyfileServiceError
44
-
45
- attr_reader :cause
46
-
47
- def initialize(message, cause)
48
- super(message)
49
- @cause = cause
50
- end
51
-
52
- end
53
-
54
20
  class CachedCookbookNotFound < StandardError
55
21
  end
56
22
 
@@ -96,4 +62,7 @@ module ChefDK
96
62
  class InvalidLockfile < StandardError
97
63
  end
98
64
 
65
+ class InvalidPolicyfileFilename < StandardError
66
+ end
67
+
99
68
  end
@@ -50,8 +50,12 @@ module ChefDK
50
50
  # Locates the omnibus directories
51
51
  #
52
52
 
53
+ def omnibus_install?
54
+ File.exist?(omnibus_chefdk_location)
55
+ end
56
+
53
57
  def omnibus_root
54
- @omnibus_root ||= omnibus_expand_path(Gem.ruby, "..", "..", "..")
58
+ @omnibus_root ||= omnibus_expand_path(expected_omnibus_root)
55
59
  end
56
60
 
57
61
  def omnibus_apps_dir
@@ -66,6 +70,10 @@ module ChefDK
66
70
  @omnibus_embedded_bin_dir ||= omnibus_expand_path(omnibus_root, "embedded", "bin")
67
71
  end
68
72
 
73
+ def omnibus_chefdk_location
74
+ @omnibus_chefdk_location ||= File.expand_path('embedded/apps/chef-dk', expected_omnibus_root)
75
+ end
76
+
69
77
  private
70
78
 
71
79
  def omnibus_expand_path(*paths)
@@ -74,6 +82,10 @@ module ChefDK
74
82
  dir
75
83
  end
76
84
 
85
+ def expected_omnibus_root
86
+ File.expand_path(File.join(Gem.ruby, "..", "..", ".."))
87
+ end
88
+
77
89
  #
78
90
  # environment vars for omnibus
79
91
  #
@@ -83,7 +95,7 @@ module ChefDK
83
95
  begin
84
96
  user_bin_dir = File.expand_path(File.join(Gem.user_dir, 'bin'))
85
97
  {
86
- 'PATH' => "#{omnibus_bin_dir}:#{user_bin_dir}:#{omnibus_embedded_bin_dir}:#{ENV['PATH']}",
98
+ 'PATH' => [ omnibus_bin_dir, user_bin_dir, omnibus_embedded_bin_dir, ENV['PATH'] ].join(File::PATH_SEPARATOR),
87
99
  'GEM_ROOT' => Gem.default_dir.inspect,
88
100
  'GEM_HOME' => Gem.user_dir,
89
101
  'GEM_PATH' => Gem.path.join(':'),
@@ -91,5 +103,11 @@ module ChefDK
91
103
  end
92
104
  end
93
105
 
106
+ # Open a file. By default, the mode is for read+write,
107
+ # and binary so that windows writes out what we tell it,
108
+ # as this is the most common case we have.
109
+ def with_file(path, mode='wb+', &block)
110
+ File.open(path, mode, &block)
111
+ end
94
112
  end
95
113
  end
@@ -279,6 +279,7 @@ module ChefDK
279
279
 
280
280
  @identifier_updated = false
281
281
  @version_updated = false
282
+ @cookbook_in_git_repo = nil
282
283
  end
283
284
 
284
285
  def cookbook_path
@@ -286,7 +287,7 @@ module ChefDK
286
287
  end
287
288
 
288
289
  def scm_profiler
289
- if File.exist?(File.join(cookbook_path, ".git"))
290
+ if cookbook_in_git_repo?
290
291
  CookbookProfiler::Git.new(cookbook_path)
291
292
  else
292
293
  CookbookProfiler::NullSCM.new(cookbook_path)
@@ -373,6 +374,23 @@ module ChefDK
373
374
  end
374
375
  end
375
376
 
377
+ def cookbook_in_git_repo?
378
+ return @cookbook_in_git_repo unless @cookbook_in_git_repo.nil?
379
+
380
+ @cookbook_in_git_repo = false
381
+
382
+ dot_git = Pathname.new(".git")
383
+ Pathname.new(cookbook_path).ascend do |parent_dir|
384
+ possbile_git_dir = parent_dir + dot_git
385
+ if possbile_git_dir.exist?
386
+ @cookbook_in_git_repo = true
387
+ break
388
+ end
389
+ end
390
+
391
+ @cookbook_in_git_repo
392
+ end
393
+
376
394
  end
377
395
  end
378
396
  end
@@ -15,8 +15,9 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ # This fixes a missing require in chef/digester:
19
+ require 'singleton'
18
20
  require 'chef/cookbook/cookbook_version_loader'
19
-
20
21
  require 'chef/cookbook/chefignore'
21
22
 
22
23
  module ChefDK
@@ -47,6 +48,15 @@ module ChefDK
47
48
  begin
48
49
  cookbook_version = loader.cookbook_version
49
50
  cookbook_version.version = version_override
51
+
52
+ # Fixup manifest.
53
+ # What happens is, the 'manifest' representation of cookbook
54
+ # version is created, it has a "name" field like foo-1.0.0, then we
55
+ # change the version to 1234.5678.9876 but the manifest is not
56
+ # regenerated so erchef rejects our upload b/c the name field
57
+ # doesn't match the expected `$cookbook_name-$version` based on the
58
+ # other fields.
59
+ cookbook_version.manifest[:name] = "#{cookbook_version.name}-#{version_override}"
50
60
  cookbook_version.freeze_version
51
61
  cookbook_version
52
62
  end