berkshelf 0.4.0.rc3 → 0.4.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_runtime_dependency 'solve', '~> 0.2.1'
20
20
  s.add_runtime_dependency 'chef', '~> 10.12.0'
21
21
  s.add_runtime_dependency 'minitar'
22
- s.add_runtime_dependency 'thor', '~> 0.15.2'
22
+ s.add_runtime_dependency 'thor', '~> 0.16.0'
23
23
 
24
24
  s.add_development_dependency 'redcarpet'
25
25
  s.add_development_dependency 'cucumber'
@@ -258,10 +258,10 @@ Feature: install cookbooks from a Berksfile
258
258
  When I run the install command
259
259
  Then the output should contain:
260
260
  """
261
- Installing artifact (0.10.0) from chef_api:
261
+ Installing artifact (0.10.2) from chef_api:
262
262
  """
263
263
  And the cookbook store should have the cookbooks:
264
- | artifact | 0.10.0 |
264
+ | artifact | 0.10.2 |
265
265
  And the exit status should be 0
266
266
 
267
267
  Scenario: with a chef_api source location specifying :knife when a Knife config is not found at the given path
@@ -0,0 +1,62 @@
1
+ Feature: --format json
2
+ As a user
3
+ I want to be able to get all output in JSON format
4
+ So I can easily parse the output in scripts
5
+
6
+ Scenario: JSON output installing a cookbook from the default location
7
+ Given I write to "Berksfile" with:
8
+ """
9
+ cookbook "mysql", "= 1.2.4"
10
+ """
11
+ When I run the install command with flags:
12
+ | --format json |
13
+ Then the output should be JSON
14
+ And the JSON at "cookbooks" should have 2 cookbooks
15
+ And the JSON at "cookbooks/0/version" should be "1.2.4"
16
+ And the JSON at "cookbooks/0/location" should be "site: 'http://cookbooks.opscode.com/api/v1/cookbooks'"
17
+
18
+ Scenario: JSON output installing a cookbook we already have
19
+ Given the cookbook store has the cookbooks:
20
+ | mysql | 1.2.4 |
21
+ And I write to "Berksfile" with:
22
+ """
23
+ cookbook "mysql", "= 1.2.4"
24
+ """
25
+ When I run the install command with flags:
26
+ | --format json |
27
+ Then the output should be JSON
28
+ And the JSON at "cookbooks" should have 1 cookbook
29
+ And the JSON at "cookbooks/0/version" should be "1.2.4"
30
+ And the JSON should not have "cookbooks/0/location"
31
+
32
+ @slow_process
33
+ Scenario: JSON output when running the upload command
34
+ Given a Berksfile with path location sources to fixtures:
35
+ | example_cookbook | example_cookbook-0.5.0 |
36
+ And the Chef server does not have the cookbooks:
37
+ | example_cookbook | 0.5.0 |
38
+ When I run the upload command with flags:
39
+ | --format json |
40
+ Then the output should be JSON
41
+ And the JSON at "cookbooks" should have 1 cookbook
42
+ And the JSON at "cookbooks/0/version" should be "0.5.0"
43
+ And the JSON should have "cookbooks/0/uploaded_to"
44
+ And the Chef server should have the cookbooks:
45
+ | example_cookbook | 0.5.0 |
46
+
47
+ Scenario: JSON output when running install command with the --shims flag
48
+ Given I write to "Berksfile" with:
49
+ """
50
+ cookbook "mysql", "1.2.4"
51
+ """
52
+ When I run the install command with flags:
53
+ | --shims |
54
+ | --format json|
55
+ Then the following directories should exist:
56
+ | cookbooks |
57
+ | cookbooks/mysql |
58
+ And the output should be JSON
59
+ And the JSON should have "shims_dir"
60
+
61
+
62
+
@@ -54,6 +54,10 @@ When /^I run the upload command$/ do
54
54
  run_simple(unescape("berks upload"), true)
55
55
  end
56
56
 
57
+ When /^I run the upload command with flags:$/ do |flags|
58
+ run_simple(unescape("berks upload #{flags.raw.join(" ")}"), false)
59
+ end
60
+
57
61
  When /^I run the cookbook command to create "(.*?)"$/ do |name|
58
62
  run_simple(unescape("berks cookbook #{name}"))
59
63
  end
@@ -0,0 +1,3 @@
1
+ Then /^the output should be JSON$/ do
2
+ lambda { parse_json(all_output) }.should_not raise_error
3
+ end
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
3
  require 'spork'
4
+ require "json_spec/cucumber"
4
5
 
5
6
  Spork.prefork do
6
7
  require 'rspec'
@@ -51,6 +52,11 @@ Spork.prefork do
51
52
  def fixtures_path
52
53
  app_root_path.join('spec/fixtures')
53
54
  end
55
+
56
+ # Set the output json_spec will parse for testing JSON responses
57
+ def last_json
58
+ all_output
59
+ end
54
60
  end
55
61
 
56
62
  Spork.each_run do
@@ -16,7 +16,7 @@ Feature: update
16
16
  When I run the update command
17
17
  Then the file "Berksfile.lock" should contain exactly:
18
18
  """
19
- cookbook 'mysql', :locked_version => '1.2.6'
19
+ cookbook 'mysql', :locked_version => '1.3.0'
20
20
  cookbook 'openssl', :locked_version => '1.0.0'
21
21
  cookbook 'windows', :locked_version => '1.3.2'
22
22
  cookbook 'chef_handler', :locked_version => '1.0.6'
@@ -107,6 +107,33 @@ module Berkshelf
107
107
  end
108
108
  end
109
109
 
110
+ # Get the appropriate Formatter object based on the formatter
111
+ # classes that have been registered.
112
+ #
113
+ # @return [~Formatter]
114
+ def formatter
115
+ @formatter ||= (formatters.has_key?(@_format) ? formatters[@_format] : Formatters::HumanReadable).new
116
+ end
117
+
118
+ # Specify a formatter identifier
119
+ #
120
+ # @param [String] format
121
+ # which formatter to use
122
+ #
123
+ # @example Berkshelf.set_format "json"
124
+ def set_format(format)
125
+ @_format = format
126
+ @formatter = nil
127
+ end
128
+
129
+ # Access the formatters map that links string symbols to Formatter
130
+ # implementations
131
+ #
132
+ # @return [Hash]
133
+ def formatters
134
+ @formatters ||= {}
135
+ end
136
+
110
137
  private
111
138
 
112
139
  def null_stream
@@ -119,3 +146,5 @@ module Berkshelf
119
146
  end
120
147
  end
121
148
  end
149
+
150
+ require 'berkshelf/formatters'
@@ -126,7 +126,7 @@ module Berkshelf
126
126
  solution = resolver.resolve
127
127
  if options[:shims]
128
128
  write_shims(options[:shims], solution)
129
- Berkshelf.ui.info "Shims written to: '#{options[:shims]}'"
129
+ Berkshelf.formatter.shims_written options[:shims]
130
130
  end
131
131
  write_lockfile(resolver.sources) unless lockfile_present?
132
132
  end
@@ -153,7 +153,7 @@ module Berkshelf
153
153
  solution = resolve(options)
154
154
 
155
155
  solution.each do |cb|
156
- Berkshelf.ui.info "Uploading #{cb.cookbook_name} (#{cb.version}) to: '#{chef_server_url}'"
156
+ Berkshelf.formatter.upload cb.cookbook_name, cb.version, chef_server_url
157
157
  uploader.upload!(cb, options)
158
158
  end
159
159
  end
@@ -212,7 +212,7 @@ module Berkshelf
212
212
  begin
213
213
  instance_eval(content)
214
214
  rescue => e
215
- raise BerksfileReadError.new(e), "An error occurred while reading the Berksfile: #{e.message}"
215
+ raise BerksfileReadError.new(e), "An error occurred while reading the Berksfile: #{e.to_s}"
216
216
  end
217
217
  self
218
218
  end
@@ -4,11 +4,19 @@ require 'berkshelf'
4
4
  module Berkshelf
5
5
  # @author Jamie Winsor <jamie@vialstudios.com>
6
6
  class Cli < Thor
7
+ class << self
8
+ def dispatch(meth, given_args, given_opts, config)
9
+ super
10
+ Berkshelf.formatter.cleanup_hook unless config[:current_task].name == "help"
11
+ end
12
+ end
13
+
7
14
  def initialize(*)
8
15
  super
9
16
  # JW TODO: Replace Chef::Knife::UI with our own UI class
10
17
  ::Berkshelf.ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
11
18
  ::Berkshelf.config_path = @options[:config]
19
+ ::Berkshelf.set_format @options[:format]
12
20
  @options = options.dup # unfreeze frozen options Hash from Thor
13
21
  end
14
22
 
@@ -26,6 +34,11 @@ module Berkshelf
26
34
  desc: "Path to Knife or Chef configuration to use.",
27
35
  aliases: "-c",
28
36
  banner: "PATH"
37
+ class_option :format,
38
+ type: :string,
39
+ desc: "Output format to use.",
40
+ aliases: "-F",
41
+ banner: "FORMAT"
29
42
 
30
43
  method_option :shims,
31
44
  type: :string,
@@ -44,7 +57,7 @@ module Berkshelf
44
57
  desc: "Path to a Berksfile to operate off of.",
45
58
  aliases: "-b",
46
59
  banner: "PATH"
47
- desc "install", "Install the Cookbooks specified by a Berksfile or a Berskfile.lock."
60
+ desc "install", "Install the Cookbooks specified by a Berksfile or a Berksfile.lock."
48
61
  def install
49
62
  berksfile = ::Berkshelf::Berksfile.from_file(options[:berksfile])
50
63
  berksfile.install(options)
@@ -102,14 +115,14 @@ module Berkshelf
102
115
 
103
116
  ::Berkshelf::InitGenerator.new([path], options).invoke_all
104
117
 
105
- ::Berkshelf.ui.info "Successfully initialized"
118
+ ::Berkshelf.formatter.msg "Successfully initialized"
106
119
  end
107
120
 
108
121
  desc "version", "Display version and copyright information"
109
122
  def version
110
- Berkshelf.ui.info version_header
111
- Berkshelf.ui.info "\n"
112
- Berkshelf.ui.info license
123
+ Berkshelf.formatter.msg version_header
124
+ Berkshelf.formatter.msg "\n"
125
+ Berkshelf.formatter.msg license
113
126
  end
114
127
 
115
128
  method_option :vagrant,
@@ -12,6 +12,8 @@ module Berkshelf
12
12
  end
13
13
 
14
14
  class InternalError < BerkshelfError; status_code(99); end
15
+ class MethodNotImplmentedError < ::Berkshelf::InternalError ; end
16
+
15
17
  class BerksfileNotFound < BerkshelfError; status_code(100); end
16
18
  class NoVersionForConstraints < BerkshelfError; status_code(101); end
17
19
  class DownloadFailure < BerkshelfError; status_code(102); end
@@ -60,5 +62,15 @@ module Berkshelf
60
62
 
61
63
  class ConstraintNotSatisfied < BerkshelfError; status_code(111); end
62
64
  class InvalidChefAPILocation < BerkshelfError; status_code(112); end
63
- class BerksfileReadError < BerkshelfError; status_code(113); end
65
+ class BerksfileReadError < BerkshelfError
66
+ def initialize(original_error)
67
+ @original_error = original_error
68
+ end
69
+
70
+ status_code(113)
71
+
72
+ def status_code
73
+ @original_error ? @original_error.status_code : 113
74
+ end
75
+ end
64
76
  end
@@ -0,0 +1,41 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ # @abstract Include and override {#install} {#use} {#upload}
4
+ # {#shims_written} {#msg} {#error} to implement.
5
+ #
6
+ # Implement {#cleanup_hook} to run any steps required to run after the task is finished
7
+ module AbstractFormatter
8
+ def cleanup_hook
9
+ # run after the task is finished
10
+ end
11
+
12
+ def install(cookbook, version, location)
13
+ raise MethodNotImplmentedError, "#install must be implemented on #{self.class}"
14
+ end
15
+
16
+ def use(cookbook, version, path = nil)
17
+ raise MethodNotImplmentedError, "#install must be implemented on #{self.class}"
18
+ end
19
+
20
+ def upload(cookbook, version, chef_server_url)
21
+ raise MethodNotImplmentedError, "#upload must be implemented on #{self.class}"
22
+ end
23
+
24
+ def shims_written(directory)
25
+ raise MethodNotImplmentedError, "#shims_written must be implemented on #{self.class}"
26
+ end
27
+
28
+ def msg(message)
29
+ raise MethodNotImplmentedError, "#msg must be implemented on #{self.class}"
30
+ end
31
+
32
+ def error(message)
33
+ raise MethodNotImplmentedError, "#error must be implemented on #{self.class}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ Dir["#{File.dirname(__FILE__)}/formatters/*.rb"].sort.each do |path|
40
+ require "berkshelf/formatters/#{File.basename(path, '.rb')}"
41
+ end
@@ -0,0 +1,33 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ class HumanReadable
4
+ include AbstractFormatter
5
+
6
+ Berkshelf.formatters["human"] = self
7
+
8
+ def install(cookbook, version, location)
9
+ Berkshelf.ui.info "Installing #{cookbook} (#{version}) from #{location}"
10
+ end
11
+
12
+ def use(cookbook, version, path=nil)
13
+ Berkshelf.ui.info "Using #{cookbook} (#{version})#{' at '+path if path}"
14
+ end
15
+
16
+ def upload(cookbook, version, chef_server_url)
17
+ Berkshelf.ui.info "Uploading #{cookbook} (#{version}) to: '#{chef_server_url}'"
18
+ end
19
+
20
+ def shims_written(directory)
21
+ Berkshelf.ui.info "Shims written to: '#{directory}'"
22
+ end
23
+
24
+ def msg(message)
25
+ Berkshelf.ui.info message
26
+ end
27
+
28
+ def error(message)
29
+ Berkshelf.ui.error message
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ module Berkshelf
2
+ module Formatters
3
+ class JSON
4
+ include AbstractFormatter
5
+
6
+ Berkshelf.formatters["json"] = self
7
+
8
+ def initialize
9
+ @output = {cookbooks: [], errors: [], messages: []}
10
+ @cookbooks = {}
11
+ super
12
+ end
13
+
14
+ def cleanup_hook
15
+ @cookbooks.each do |name, details|
16
+ details[:name] = name
17
+ @output[:cookbooks] << details
18
+ end
19
+ print @output.to_json
20
+ end
21
+
22
+ def install(cookbook, version, location)
23
+ @cookbooks[cookbook] ||= {}
24
+ @cookbooks[cookbook][:version] = version
25
+ @cookbooks[cookbook][:location] = location
26
+ end
27
+
28
+ def use(cookbook, version, path=nil)
29
+ @cookbooks[cookbook] ||= {}
30
+ @cookbooks[cookbook][:version] = version
31
+ @cookbooks[cookbook][:location] = path if path
32
+ end
33
+
34
+ def upload(cookbook, version, chef_server_url)
35
+ @cookbooks[cookbook] ||= {}
36
+ @cookbooks[cookbook][:version] = version
37
+ @cookbooks[cookbook][:uploaded_to] = chef_server_url
38
+ end
39
+
40
+ def shims_written(directory)
41
+ @output[:shims_dir] = directory
42
+ end
43
+
44
+ def msg(message)
45
+ @output[:messages] << message
46
+ end
47
+
48
+ def error(message)
49
+ @output[:errors] << message
50
+ end
51
+ end
52
+ end
53
+ end
@@ -126,7 +126,7 @@ module Berkshelf
126
126
  # @return [Boolean]
127
127
  def install_source(source)
128
128
  downloader.download!(source)
129
- Berkshelf.ui.info "Installing #{source.name} (#{source.cached_cookbook.version}) from #{source.location}"
129
+ Berkshelf.formatter.install source.name, source.cached_cookbook.version, source.location
130
130
  end
131
131
 
132
132
  # Use the given source to create a constraint solution if the source has been downloaded or can
@@ -158,9 +158,8 @@ module Berkshelf
158
158
  get_source(source).cached_cookbook = cached
159
159
  end
160
160
 
161
- msg = "Using #{cached.cookbook_name} (#{cached.version})"
162
- msg << " at #{source.location}" if source.location.is_a?(CookbookSource::PathLocation)
163
- Berkshelf.ui.info msg
161
+ path = source.location.is_a?(CookbookSource::PathLocation) ? "#{source.location}" : nil
162
+ Berkshelf.formatter.use cached.cookbook_name, cached.version, path
164
163
 
165
164
  true
166
165
  end
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "0.4.0.rc3"
2
+ VERSION = "0.4.0.rc4"
3
3
  end
@@ -1,5 +1,5 @@
1
1
  cookbook 'nginx', :locked_version => '0.101.0'
2
- cookbook 'build-essential', :locked_version => '1.0.2'
2
+ cookbook 'build-essential', :locked_version => '1.1.0'
3
3
  cookbook 'runit', :locked_version => '0.15.0'
4
- cookbook 'bluepill', :locked_version => '1.0.4'
4
+ cookbook 'bluepill', :locked_version => '1.0.6'
5
5
  cookbook 'ohai', :locked_version => '1.0.2'
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Berkshelf
4
+ module Formatters
5
+ class TestFormatter
6
+ include AbstractFormatter
7
+ end
8
+
9
+ describe AbstractFormatter do
10
+
11
+ subject { TestFormatter.new }
12
+
13
+ it "has abstract methods for all the messaging modes" do
14
+ lambda { subject.install("my_coobook","1.2.3","http://community") }.should raise_error(MethodNotImplmentedError)
15
+ lambda { subject.use("my_coobook","1.2.3") }.should raise_error(MethodNotImplmentedError)
16
+ lambda { subject.use("my_coobook","1.2.3","http://community") }.should raise_error(MethodNotImplmentedError)
17
+ lambda { subject.upload("my_coobook","1.2.3","http://chef_server") }.should raise_error(MethodNotImplmentedError)
18
+ lambda { subject.shims_written("/Users/jcocktosten") }.should raise_error(MethodNotImplmentedError)
19
+ lambda { subject.msg("something you should know") }.should raise_error(MethodNotImplmentedError)
20
+ lambda { subject.error("whoa this is bad") }.should raise_error(MethodNotImplmentedError)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -14,8 +14,8 @@ describe Berkshelf::Lockfile do
14
14
  Berkshelf::Lockfile.new(resolver.sources).write
15
15
 
16
16
  File.read('Berksfile.lock').split(/\r?\n/).sort.should == [
17
- "cookbook 'bluepill', :locked_version => '1.0.4'",
18
- "cookbook 'build-essential', :locked_version => '1.0.2'",
17
+ "cookbook 'bluepill', :locked_version => '1.0.6'",
18
+ "cookbook 'build-essential', :locked_version => '1.1.0'",
19
19
  "cookbook 'nginx', :locked_version => '0.101.0'",
20
20
  "cookbook 'ohai', :locked_version => '1.0.2'",
21
21
  "cookbook 'runit', :locked_version => '0.15.0'"
@@ -45,5 +45,32 @@ describe Berkshelf do
45
45
  subject.load_config
46
46
  end
47
47
  end
48
+
49
+ describe "::formatter" do
50
+ context "with default formatter" do
51
+ it "should be human readable" do
52
+ Berkshelf.formatter.should be_an_instance_of(Berkshelf::Formatters::HumanReadable)
53
+ end
54
+ end
55
+
56
+ context "with a custom formatter" do
57
+ before(:all) do
58
+ Berkshelf.instance_eval { @formatter = nil }
59
+ end
60
+
61
+ class CustomFormatter
62
+ include Berkshelf::Formatters::AbstractFormatter
63
+ Berkshelf.formatters["custom"] = self
64
+ end
65
+
66
+ before do
67
+ Berkshelf.set_format "custom"
68
+ end
69
+
70
+ it "should be the custom class" do
71
+ Berkshelf.formatter.should be_an_instance_of(CustomFormatter)
72
+ end
73
+ end
74
+ end
48
75
  end
49
76
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkshelf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.rc3
4
+ version: 0.4.0.rc4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-08-20 00:00:00.000000000 Z
15
+ date: 2012-08-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: solve
@@ -69,7 +69,7 @@ dependencies:
69
69
  requirements:
70
70
  - - ~>
71
71
  - !ruby/object:Gem::Version
72
- version: 0.15.2
72
+ version: 0.16.0
73
73
  type: :runtime
74
74
  prerelease: false
75
75
  version_requirements: !ruby/object:Gem::Requirement
@@ -77,7 +77,7 @@ dependencies:
77
77
  requirements:
78
78
  - - ~>
79
79
  - !ruby/object:Gem::Version
80
- version: 0.15.2
80
+ version: 0.16.0
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: redcarpet
83
83
  requirement: !ruby/object:Gem::Requirement
@@ -373,11 +373,13 @@ files:
373
373
  - features/cookbook_command.feature
374
374
  - features/init_command.feature
375
375
  - features/install.feature
376
+ - features/json_formatter.feature
376
377
  - features/lockfile.feature
377
378
  - features/step_definitions/berksfile_steps.rb
378
379
  - features/step_definitions/chef_server_steps.rb
379
380
  - features/step_definitions/cli_steps.rb
380
381
  - features/step_definitions/filesystem_steps.rb
382
+ - features/step_definitions/json_steps.rb
381
383
  - features/support/env.rb
382
384
  - features/update.feature
383
385
  - features/upload_command.feature
@@ -418,6 +420,9 @@ files:
418
420
  - lib/berkshelf/downloader.rb
419
421
  - lib/berkshelf/dsl.rb
420
422
  - lib/berkshelf/errors.rb
423
+ - lib/berkshelf/formatters.rb
424
+ - lib/berkshelf/formatters/human_readable.rb
425
+ - lib/berkshelf/formatters/json.rb
421
426
  - lib/berkshelf/git.rb
422
427
  - lib/berkshelf/init_generator.rb
423
428
  - lib/berkshelf/lockfile.rb
@@ -431,6 +436,7 @@ files:
431
436
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
432
437
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
433
438
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
439
+ - spec/fixtures/cookbooks/example_cookbook/Berksfile.lock
434
440
  - spec/fixtures/cookbooks/example_cookbook/README.md
435
441
  - spec/fixtures/cookbooks/example_cookbook/metadata.rb
436
442
  - spec/fixtures/cookbooks/example_cookbook/recipes/default.rb
@@ -471,6 +477,7 @@ files:
471
477
  - spec/unit/berkshelf/core_ext/fileutils_spec.rb
472
478
  - spec/unit/berkshelf/downloader_spec.rb
473
479
  - spec/unit/berkshelf/dsl_spec.rb
480
+ - spec/unit/berkshelf/formatters_spec.rb
474
481
  - spec/unit/berkshelf/git_spec.rb
475
482
  - spec/unit/berkshelf/init_generator_spec.rb
476
483
  - spec/unit/berkshelf/lockfile_spec.rb
@@ -507,11 +514,13 @@ test_files:
507
514
  - features/cookbook_command.feature
508
515
  - features/init_command.feature
509
516
  - features/install.feature
517
+ - features/json_formatter.feature
510
518
  - features/lockfile.feature
511
519
  - features/step_definitions/berksfile_steps.rb
512
520
  - features/step_definitions/chef_server_steps.rb
513
521
  - features/step_definitions/cli_steps.rb
514
522
  - features/step_definitions/filesystem_steps.rb
523
+ - features/step_definitions/json_steps.rb
515
524
  - features/support/env.rb
516
525
  - features/update.feature
517
526
  - features/upload_command.feature
@@ -520,6 +529,7 @@ test_files:
520
529
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
521
530
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
522
531
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
532
+ - spec/fixtures/cookbooks/example_cookbook/Berksfile.lock
523
533
  - spec/fixtures/cookbooks/example_cookbook/README.md
524
534
  - spec/fixtures/cookbooks/example_cookbook/metadata.rb
525
535
  - spec/fixtures/cookbooks/example_cookbook/recipes/default.rb
@@ -560,6 +570,7 @@ test_files:
560
570
  - spec/unit/berkshelf/core_ext/fileutils_spec.rb
561
571
  - spec/unit/berkshelf/downloader_spec.rb
562
572
  - spec/unit/berkshelf/dsl_spec.rb
573
+ - spec/unit/berkshelf/formatters_spec.rb
563
574
  - spec/unit/berkshelf/git_spec.rb
564
575
  - spec/unit/berkshelf/init_generator_spec.rb
565
576
  - spec/unit/berkshelf/lockfile_spec.rb