chef-dk 0.3.0 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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