chef-dk 0.4.0 → 0.5.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -3
  3. data/README.md +20 -15
  4. data/lib/chef-dk/cli.rb +18 -1
  5. data/lib/chef-dk/command/verify.rb +1 -1
  6. data/lib/chef-dk/policyfile/cookbook_location_specification.rb +5 -1
  7. data/lib/chef-dk/policyfile/read_cookbook_for_compat_mode_upload.rb +44 -0
  8. data/lib/chef-dk/policyfile/uploader.rb +58 -6
  9. data/lib/chef-dk/policyfile_lock.rb +42 -0
  10. data/lib/chef-dk/skeletons/code_generator/files/default/{repo/cookbooks → cookbook_readmes}/README-policy.md +0 -0
  11. data/lib/chef-dk/skeletons/code_generator/files/default/{repo/cookbooks → cookbook_readmes}/README.md +1 -1
  12. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -0
  13. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +3 -0
  14. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -0
  15. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/README.md +13 -18
  16. data/lib/chef-dk/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +4 -0
  17. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/README.md +7 -3
  18. data/lib/chef-dk/skeletons/code_generator/files/default/repo/environments/example.json +13 -0
  19. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/README.md +6 -13
  20. data/lib/chef-dk/skeletons/code_generator/files/default/repo/roles/example.json +13 -0
  21. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +5 -1
  22. data/lib/chef-dk/skeletons/code_generator/recipes/cookbook.rb +5 -1
  23. data/lib/chef-dk/skeletons/code_generator/recipes/repo.rb +5 -20
  24. data/lib/chef-dk/version.rb +1 -1
  25. data/lib/kitchen/provisioner/policyfile_zero.rb +21 -9
  26. data/spec/spec_helper.rb +8 -0
  27. data/spec/unit/cli_spec.rb +49 -3
  28. data/spec/unit/command/generator_commands/app_spec.rb +1 -1
  29. data/spec/unit/command/generator_commands/cookbook_spec.rb +1 -1
  30. data/spec/unit/command/generator_commands/repo_spec.rb +46 -50
  31. data/spec/unit/policyfile/uploader_spec.rb +225 -171
  32. data/spec/unit/policyfile_evaluation_spec.rb +16 -0
  33. data/spec/unit/policyfile_lock_build_spec.rb +156 -0
  34. metadata +18 -9
  35. data/lib/chef-dk/skeletons/code_generator/files/default/repo/Rakefile +0 -65
  36. data/lib/chef-dk/skeletons/code_generator/files/default/repo/certificates/README.md +0 -19
  37. data/lib/chef-dk/skeletons/code_generator/templates/default/repo/config/rake.rb.erb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc8cebdbcdaa5a3c3f4e2b3bf18fc1c3caca8843
4
- data.tar.gz: 9f57e9e37cf5b66823e9a6e3f6470afb369177fe
3
+ metadata.gz: ba6c0ab110f7a9fdc6434c4999a965e966a6d764
4
+ data.tar.gz: 1cdc0b41d6847ad1db3f23a83bcc02eaa33f5c1c
5
5
  SHA512:
6
- metadata.gz: 0f3578a7438281d5360cc4278e16e424e84c1dcec4f7087a8d9ce9dbbecd8a0e74c3b67d5fde04128bf58ee7815a21f3a48e12d444241928f2f2dd75cc1dc082
7
- data.tar.gz: e2e691462cb8febe46e0fec9d07f5f6f21e1bfc73bb89c7bb7556e475253f25ad75f521521cdd523f61c62ceaa3ab7323aead451a568c5339e9bd64c0ca61e21
6
+ metadata.gz: 74ad30f7c8a851fec368a512fb64c352b5bd9e6275598658680394469933a8b9af12fbdeb510f5d04b358ea21ef97ff8afc1b418cf389034944234b6e87fff6c
7
+ data.tar.gz: a621d898759ebe1527bf1b4c43e7619bbc2c6a4ca001c0fc625aea937c2b9087d55262f15f8a7e19428c2e57cadbcf0f5bd2f2aa1657e15007a4f8fbd5ca46c4
@@ -11,9 +11,7 @@ We utilize **Github Issues** for issue tracking and contributions. You can contr
11
11
 
12
12
  We have a 3 step process that utilizes **Github Issues**:
13
13
 
14
- 1. Sign our
15
- [Individual Contributor License Agreement (CLA)](https://secure.echosign.com/public/hostedForm?formid=PJIF5694K6L)
16
- or [Corporate CLA](https://secure.echosign.com/public/hostedForm?formid=PIE6C7AX856) online once.
14
+ 1. Sign or be added to an existing [Contributor License Agreement (CLA)](https://supermarket.chef.io/become-a-contributor).
17
15
  2. Create a Github Pull Request.
18
16
  3. Do [Code Review](#cr) with the **Chef Engineering Team** or **Chef Core Committers** on the pull request.
19
17
 
data/README.md CHANGED
@@ -17,7 +17,7 @@ package is built via the 'chefdk' project in
17
17
  You can get the [latest release of ChefDK from the downloads page][ChefDK].
18
18
 
19
19
  On Mac OS X, you can also use [homebrew-cask](http://caskroom.io)
20
- to install ChefDK.
20
+ to `brew cask install chefdk`.
21
21
 
22
22
  Once you install the package, the `chef-client` suite, `berks`,
23
23
  `kitchen`, and this application (`chef`) will be symlinked into your
@@ -104,8 +104,8 @@ in our build cluster to verify each build).
104
104
 
105
105
  ### `chef exec`
106
106
  `chef exec <command>` runs any arbitrary shell command with the PATH
107
- environment variable and the ruby environment variables (GEM_HOME,
108
- GEM_PATH, etc) setup to point at the embedded ChefDK omnibus environment.
107
+ environment variable and the ruby environment variables (`GEM_HOME`,
108
+ `GEM_PATH`, etc.) setup to point at the embedded ChefDK omnibus environment.
109
109
 
110
110
  ### `chef shell-init`
111
111
  `chef shell-init SHELL_NAME` emits shell commands that modify your
@@ -114,11 +114,11 @@ help you decide if this is desirable and instructions, see "Using ChefDK
114
114
  as Your Primary Development Environment" below.
115
115
 
116
116
  ### `chef install`
117
- `chef install` reads a Policyfile.rb document, which contains a
117
+ `chef install` reads a `Policyfile.rb` document, which contains a
118
118
  `run_list` and optional cookbook version constraints, finds a set of
119
119
  cookbooks that provide the desired recipes and meet dependency
120
- constraints, and emits a Policyfile.lock.json describing the expanded
121
- run list and locked cookbook set. The Policyfile.lock.json can be used
120
+ constraints, and emits a `Policyfile.lock.json` describing the expanded
121
+ run list and locked cookbook set. The `Policyfile.lock.json` can be used
122
122
  to install the cookbooks on another machine. The policy lock can be
123
123
  uploaded to a Chef Server (via the `chef push` command) to apply the
124
124
  expanded run list and locked cookbook set to nodes in your
@@ -152,21 +152,27 @@ ChefDK's environment.
152
152
 
153
153
  To try it temporarily, in a new terminal session, run:
154
154
 
155
- eval "$(chef shell-init SHELL_NAME)"
155
+ ```sh
156
+ eval "$(chef shell-init SHELL_NAME)"
157
+ ```
156
158
 
157
- where `SHELL_NAME` is the name of your shell, (usually bash, but zsh is
159
+ where `SHELL_NAME` is the name of your shell (usually bash, but zsh is
158
160
  also common). This modifies your `PATH` and `GEM_*` environment
159
161
  variables to include ChefDK's paths (run without the `eval` to see the
160
162
  generated code). Now your default `ruby` and associated tools will be
161
163
  the ones from ChefDK:
162
164
 
163
- which ruby
164
- # => /opt/chefdk/embedded/bin/ruby
165
+ ```sh
166
+ which ruby
167
+ # => /opt/chefdk/embedded/bin/ruby
168
+ ```
165
169
 
166
170
  To add ChefDK to your shell's environment permanently, add the
167
171
  initialization step to your shell's profile:
168
172
 
169
- echo 'eval "$(chef shell-init SHELL_NAME)"' >> ~/.YOUR_SHELL_PROFILE
173
+ ```sh
174
+ echo 'eval "$(chef shell-init SHELL_NAME)"' >> ~/.YOUR_SHELL_PROFILE
175
+ ```
170
176
 
171
177
  Where `YOUR_SHELL_PROFILE` is `~/.bash_profile` for most bash users,
172
178
  `~/.zshrc` for zsh, and `~/.bashrc` on Ubuntu.
@@ -177,7 +183,7 @@ Where `YOUR_SHELL_PROFILE` is `~/.bash_profile` for most bash users,
177
183
 
178
184
  You can uninstall Chef Development Kit on Mac using below commands:
179
185
 
180
- ```
186
+ ```sh
181
187
  # Remove the installed files
182
188
  sudo rm -rf /opt/chefdk
183
189
 
@@ -186,7 +192,6 @@ sudo pkgutil --forget com.getchef.pkg.chefdk
186
192
 
187
193
  # Remove the symlinks under /usr/bin for Chef Development Kit
188
194
  ls -la /usr/bin | egrep '/opt/chefdk' | awk '{ print $9 }' | sudo xargs -I % rm -f /usr/bin/%
189
-
190
195
  ```
191
196
 
192
197
  ### Windows
@@ -198,7 +203,7 @@ Kit from your system.
198
203
 
199
204
  You can use `rpm` to uninstall Chef Development Kit on RHEL based systems:
200
205
 
201
- ```
206
+ ```sh
202
207
  rpm -qa *chefdk*
203
208
  yum remove <package>
204
209
  rm -rf /opt/chefdk
@@ -209,7 +214,7 @@ rm -rf ~/.chefdk
209
214
 
210
215
  You can use `dpkg` to uninstall Chef Development Kit on Ubuntu based systems:
211
216
 
212
- ```
217
+ ```sh
213
218
  dpkg --list | grep chefdk # or dpkg --status chefdk
214
219
 
215
220
  # Purge chefdk from the system.
@@ -22,11 +22,14 @@ require 'chef-dk/builtin_commands'
22
22
  require 'chef-dk/helpers'
23
23
  require 'chef-dk/ui'
24
24
  require 'chef/util/path_helper'
25
+ require 'chef/mixin/shell_out'
26
+ require 'bundler'
25
27
 
26
28
  module ChefDK
27
29
  class CLI
28
30
  include Mixlib::CLI
29
31
  include ChefDK::Helpers
32
+ include Chef::Mixin::ShellOut
30
33
 
31
34
  banner(<<-BANNER)
32
35
  Usage:
@@ -84,13 +87,27 @@ BANNER
84
87
  def handle_options
85
88
  parse_options(argv)
86
89
  if config[:version]
87
- msg("Chef Development Kit Version: #{ChefDK::VERSION}")
90
+ show_version
88
91
  else
89
92
  show_help
90
93
  end
91
94
  exit 0
92
95
  end
93
96
 
97
+ def show_version
98
+ msg("Chef Development Kit Version: #{ChefDK::VERSION}")
99
+
100
+ ["chef-client", "berks", "kitchen"].each do |component|
101
+ result = Bundler.with_clean_env { shell_out("#{component} --version") }
102
+ if result.exitstatus != 0
103
+ msg("#{component} version: ERROR")
104
+ else
105
+ version = result.stdout.scan(/[\d+\.]+\S+/).join
106
+ msg("#{component} version: #{version}")
107
+ end
108
+ end
109
+ end
110
+
94
111
  def show_help
95
112
  msg(banner)
96
113
  msg("\nAvailable Commands:")
@@ -98,7 +98,7 @@ module ChefDK
98
98
 
99
99
  add_component "chef-client" do |c|
100
100
  c.base_dir = "chef"
101
- c.unit_test { sh("bundle exec rspec -fp spec/unit") }
101
+ c.unit_test { sh("bundle exec rspec -fp -t '~volatile_from_verify' spec/unit") }
102
102
  c.integration_test { sh("bundle exec rspec -fp spec/integration spec/functional") }
103
103
 
104
104
  c.smoke_test do
@@ -80,7 +80,7 @@ module ChefDK
80
80
 
81
81
  def errors
82
82
  error_messages = []
83
- if installer.nil?
83
+ if source_options_invalid?
84
84
  error_messages << "Cookbook `#{name}' has invalid source options `#{source_options.inspect}'"
85
85
  end
86
86
  error_messages
@@ -124,6 +124,10 @@ module ChefDK
124
124
  installer.lock_data
125
125
  end
126
126
 
127
+ def source_options_invalid?
128
+ !source_options.empty? && installer.nil?
129
+ end
130
+
127
131
  end
128
132
  end
129
133
  end
@@ -22,6 +22,48 @@ require 'chef/cookbook/chefignore'
22
22
 
23
23
  module ChefDK
24
24
  module Policyfile
25
+
26
+ class CookbookLoaderWithChefignore
27
+
28
+ # Convenience method to load a cookbook and return a
29
+ # Chef::CookbookVersion object.
30
+ #
31
+ def self.load(name, directory_path)
32
+ new(name, directory_path).cookbook_version
33
+ end
34
+
35
+ attr_reader :cookbook_name
36
+ attr_reader :directory_path
37
+
38
+ def initialize(cookbook_name, directory_path)
39
+ @cookbook_name = cookbook_name
40
+ @directory_path = directory_path
41
+
42
+ @cookbook_version = nil
43
+ @loader = nil
44
+ end
45
+
46
+ def cookbook_version
47
+ @cookbook_version ||= loader.cookbook_version
48
+ end
49
+
50
+ def loader
51
+ @loader ||=
52
+ begin
53
+ cbvl = Chef::Cookbook::CookbookVersionLoader.new(directory_path, chefignore)
54
+ cbvl.load!
55
+ cbvl
56
+ end
57
+ end
58
+
59
+ def chefignore
60
+ @chefignore ||= Chef::Cookbook::Chefignore.new(File.join(directory_path, "chefignore"))
61
+ end
62
+
63
+ end
64
+
65
+ # TODO: when compat mode is removed, this class should be removed and the
66
+ # file should be renamed
25
67
  class ReadCookbookForCompatModeUpload
26
68
 
27
69
  # Convenience method to load a cookbook, set up name and version overrides
@@ -47,7 +89,9 @@ module ChefDK
47
89
  @cookbook_version ||=
48
90
  begin
49
91
  cookbook_version = loader.cookbook_version
92
+ # TODO: dont do this for non-compat mode
50
93
  cookbook_version.version = version_override
94
+ # TODO: dont do this either
51
95
 
52
96
  # Fixup manifest.
53
97
  # What happens is, the 'manifest' representation of cookbook
@@ -49,7 +49,16 @@ module ChefDK
49
49
  end
50
50
 
51
51
  def upload
52
- ui.msg("WARN: Uploading policy to policy group #{policy_group} in compatibility mode")
52
+ ui.msg("Uploading policy to policy group #{policy_group}")
53
+
54
+ if using_policy_document_native_api?
55
+ ui.msg(<<-DRAGONS)
56
+ WARN: Using native policy API preview mode. You may be required to delete and
57
+ re-upload this data when upgrading to the final release version of the feature.
58
+ DRAGONS
59
+ else
60
+ ui.msg("WARN: Uploading policy to policy group #{policy_group} in compatibility mode")
61
+ end
53
62
 
54
63
  upload_cookbooks
55
64
  upload_policy
@@ -65,7 +74,7 @@ module ChefDK
65
74
  end
66
75
 
67
76
  def upload_policy_native
68
- http_client.put("/policies/#{policy_group}/#{policy_name}", policyfile_lock.to_lock)
77
+ http_client.put("/policy_groups/#{policy_group}/policies/#{policy_name}", policyfile_lock.to_lock)
69
78
  end
70
79
 
71
80
  def data_bag_create
@@ -97,12 +106,17 @@ module ChefDK
97
106
 
98
107
  def uploader
99
108
  # TODO: uploader runs cookbook validation; we want to do this at a different time.
100
- @uploader ||= Chef::CookbookUploader.new(cookbook_versions_to_upload, :rest => http_client)
109
+ @uploader ||= Chef::CookbookUploader.new(cookbook_versions_to_upload, rest: http_client, policy_mode: using_policy_document_native_api?)
101
110
  end
102
111
 
103
112
  def cookbook_versions_to_upload
104
113
  cookbook_versions_for_policy.inject([]) do |versions_to_upload, cookbook_with_lock|
105
114
  cb = cookbook_with_lock.cookbook
115
+ # When we abandon custom identifier support in favor of the one true
116
+ # hash, identifier generation code can be moved into chef proper and
117
+ # this can be removed.
118
+ cb.identifier = cookbook_with_lock.lock.identifier
119
+
106
120
  versions_to_upload << cb unless remote_already_has_cookbook?(cb)
107
121
  versions_to_upload
108
122
  end
@@ -111,13 +125,27 @@ module ChefDK
111
125
  def remote_already_has_cookbook?(cookbook)
112
126
  return false unless existing_cookbook_on_remote.key?(cookbook.name.to_s)
113
127
 
128
+ if using_policy_document_native_api?
129
+ native_mode_cookbook_exists_on_remote?(cookbook)
130
+ else
131
+ compat_mode_cookbook_exists_on_remote?(cookbook)
132
+ end
133
+ end
134
+
135
+ def native_mode_cookbook_exists_on_remote?(cookbook)
136
+ existing_cookbook_on_remote[cookbook.name.to_s]["versions"].any? do |cookbook_info|
137
+ cookbook_info["identifier"] == cookbook.identifier
138
+ end
139
+ end
140
+
141
+ def compat_mode_cookbook_exists_on_remote?(cookbook)
114
142
  existing_cookbook_on_remote[cookbook.name.to_s]["versions"].any? do |cookbook_info|
115
143
  cookbook_info["version"] == cookbook.version
116
144
  end
117
145
  end
118
146
 
119
147
  def existing_cookbook_on_remote
120
- @existing_cookbook_on_remote ||= http_client.get('cookbooks?num_versions=all')
148
+ @existing_cookbook_on_remote ||= http_client.get(list_cookbooks_url)
121
149
  end
122
150
 
123
151
  # An Array of Chef::CookbookVersion objects representing the full set that
@@ -125,7 +153,23 @@ module ChefDK
125
153
  def cookbook_versions_for_policy
126
154
  return @cookbook_versions_for_policy if @cookbook_versions_for_policy
127
155
  policyfile_lock.validate_cookbooks!
128
- @cookbook_versions_for_policy = policyfile_lock.cookbook_locks.map do |name, lock|
156
+ @cookbook_versions_for_policy =
157
+ if using_policy_document_native_api?
158
+ load_cookbooks_in_native_mode
159
+ else
160
+ load_cookbooks_in_compat_mode
161
+ end
162
+ end
163
+
164
+ def load_cookbooks_in_native_mode
165
+ policyfile_lock.cookbook_locks.map do |name, lock|
166
+ cb = CookbookLoaderWithChefignore.load(name, lock.cookbook_path)
167
+ LockedCookbookForUpload.new(cb, lock)
168
+ end
169
+ end
170
+
171
+ def load_cookbooks_in_compat_mode
172
+ policyfile_lock.cookbook_locks.map do |name, lock|
129
173
  cb = ReadCookbookForCompatModeUpload.load(name, lock.dotted_decimal_identifier, lock.cookbook_path)
130
174
  LockedCookbookForUpload.new(cb, lock)
131
175
  end
@@ -137,8 +181,16 @@ module ChefDK
137
181
 
138
182
  private
139
183
 
184
+ def list_cookbooks_url
185
+ if using_policy_document_native_api?
186
+ 'cookbook_artifacts?num_versions=all'
187
+ else
188
+ 'cookbooks?num_versions=all'
189
+ end
190
+ end
191
+
140
192
  def upload_cookbooks
141
- ui.msg("WARN: Uploading cookbooks using semver compat mode")
193
+ ui.msg("WARN: Uploading cookbooks using semver compat mode") unless using_policy_document_native_api?
142
194
 
143
195
  uploader.upload_cookbooks unless cookbook_versions_to_upload.empty?
144
196
 
@@ -15,6 +15,8 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ require 'digest/sha1'
19
+
18
20
  require 'chef-dk/policyfile/storage_config'
19
21
  require 'chef-dk/policyfile/cookbook_locks'
20
22
  require 'chef-dk/policyfile/solution_dependencies'
@@ -125,6 +127,7 @@ module ChefDK
125
127
 
126
128
  def to_lock
127
129
  {}.tap do |lock|
130
+ lock["revision_id"] = revision_id
128
131
  lock["name"] = name
129
132
  lock["run_list"] = run_list
130
133
  lock["named_run_lists"] = named_run_lists unless named_run_lists.empty?
@@ -133,6 +136,45 @@ module ChefDK
133
136
  end
134
137
  end
135
138
 
139
+ # Returns a fingerprint of the PolicyfileLock by computing the SHA1 hash of
140
+ # #canonical_revision_string
141
+ def revision_id
142
+ Digest::SHA1.new.hexdigest(canonical_revision_string)
143
+ end
144
+
145
+ # Generates a string representation of the lock data in a specialized
146
+ # format suitable for generating a checksum of the lock itself. Only data
147
+ # that modifies the behavior of a chef-client using the lockfile is
148
+ # included in this format; for example, a modification to the source
149
+ # options in a `Policyfile.rb` that yields identical code (such as
150
+ # switching to a github fork at the same revision) will not cause a change
151
+ # in the PolicyfileLock's canonical_revision_string.
152
+ #
153
+ # This format is intended to be used only for generating an identifier for
154
+ # a particular revision of a PolicyfileLock. It should not be used as a
155
+ # serialization format, and is not guaranteed to be a stable interface.
156
+ def canonical_revision_string
157
+ canonical_rev_text = ""
158
+
159
+ canonical_rev_text << "name:#{name}\n"
160
+
161
+ run_list.each do |item|
162
+ canonical_rev_text << "run-list-item:#{item}\n"
163
+ end
164
+
165
+ named_run_lists.each do |name, run_list|
166
+ run_list.each do |item|
167
+ canonical_rev_text << "named-run-list:#{name};run-list-item:#{item}\n"
168
+ end
169
+ end
170
+
171
+ cookbook_locks_for_lockfile.each do |name, lock|
172
+ canonical_rev_text << "cookbook:#{name};id:#{lock["identifier"]}\n"
173
+ end
174
+
175
+ canonical_rev_text
176
+ end
177
+
136
178
  def cookbook_locks_for_lockfile
137
179
  cookbook_locks.inject({}) do |locks_map, (name, location_spec)|
138
180
  location_spec.validate!
@@ -1,4 +1,4 @@
1
- This directory contains the cookbooks used to configure systems in your infrastructure with Chef.
1
+ This directory contains the cookbooks used to configure systems in your infrastructure with Chef - an example basic cookbook called `example` has been automatically created for you.
2
2
 
3
3
  Knife needs to be configured to know where the cookbooks are located with the `cookbook_path` setting. If this is not set, then several cookbook operations will fail to work properly.
4
4
 
@@ -0,0 +1,7 @@
1
+ # This is a Chef attributes file. It can be used to specify default and override
2
+ # attributes to be applied to nodes that run this cookbook.
3
+
4
+ # Set a default name
5
+ default["example"]["name"] = "Sam Doe"
6
+
7
+ # For further information, see the Chef documentation (http://docs.getchef.com/essentials_cookbook_attribute_files.html).