berkshelf 2.0.3 → 2.0.4
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.
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -0
- data/berkshelf.gemspec +5 -4
- data/features/berksfile.feature +56 -0
- data/features/install_command.feature +99 -13
- data/features/json_formatter.feature +1 -1
- data/features/lockfile.feature +50 -23
- data/features/step_definitions/filesystem_steps.rb +14 -1
- data/features/step_definitions/json_steps.rb +1 -1
- data/features/update_command.feature +2 -2
- data/features/upload_command.feature +0 -1
- data/lib/berkshelf.rb +1 -15
- data/lib/berkshelf/berksfile.rb +27 -21
- data/lib/berkshelf/cli.rb +2 -3
- data/lib/berkshelf/commands/test_command.rb +4 -2
- data/lib/berkshelf/community_rest.rb +6 -0
- data/lib/berkshelf/cookbook_source.rb +15 -37
- data/lib/berkshelf/core_ext/rbzip2.rb +8 -0
- data/lib/berkshelf/downloader.rb +56 -47
- data/lib/berkshelf/errors.rb +9 -2
- data/lib/berkshelf/formatters/human_readable.rb +10 -3
- data/lib/berkshelf/formatters/json.rb +7 -3
- data/lib/berkshelf/git.rb +2 -1
- data/lib/berkshelf/init_generator.rb +18 -12
- data/lib/berkshelf/location.rb +4 -14
- data/lib/berkshelf/locations/chef_api_location.rb +0 -1
- data/lib/berkshelf/locations/git_location.rb +1 -2
- data/lib/berkshelf/locations/path_location.rb +35 -11
- data/lib/berkshelf/locations/site_location.rb +0 -1
- data/lib/berkshelf/resolver.rb +18 -14
- data/lib/berkshelf/version.rb +1 -1
- data/spec/fixtures/cookbooks/example_cookbook/Berksfile +1 -0
- data/spec/unit/berkshelf/berksfile_spec.rb +30 -2
- data/spec/unit/berkshelf/community_rest_spec.rb +49 -11
- data/spec/unit/berkshelf/cookbook_source_spec.rb +11 -7
- data/spec/unit/berkshelf/downloader_spec.rb +1 -1
- data/spec/unit/berkshelf/location_spec.rb +0 -6
- data/spec/unit/berkshelf/locations/chef_api_location_spec.rb +0 -4
- data/spec/unit/berkshelf/locations/git_location_spec.rb +0 -5
- data/spec/unit/berkshelf/locations/path_location_spec.rb +0 -41
- data/spec/unit/berkshelf_spec.rb +0 -25
- metadata +37 -16
data/lib/berkshelf/errors.rb
CHANGED
@@ -123,7 +123,9 @@ module Berkshelf
|
|
123
123
|
class BerksfileReadError < BerkshelfError
|
124
124
|
# @param [#status_code] original_error
|
125
125
|
def initialize(original_error)
|
126
|
-
@original_error
|
126
|
+
@original_error = original_error
|
127
|
+
@error_message = original_error.to_s
|
128
|
+
@error_backtrace = original_error.backtrace
|
127
129
|
end
|
128
130
|
|
129
131
|
status_code(113)
|
@@ -132,11 +134,16 @@ module Berkshelf
|
|
132
134
|
@original_error.respond_to?(:status_code) ? @original_error.status_code : 113
|
133
135
|
end
|
134
136
|
|
137
|
+
alias_method :original_backtrace, :backtrace
|
138
|
+
def backtrace
|
139
|
+
Array(@error_backtrace) + Array(original_backtrace)
|
140
|
+
end
|
141
|
+
|
135
142
|
def to_s
|
136
143
|
[
|
137
144
|
"An error occurred while reading the Berksfile:",
|
138
145
|
"",
|
139
|
-
"
|
146
|
+
" #{@error_message}",
|
140
147
|
].join("\n")
|
141
148
|
end
|
142
149
|
end
|
@@ -18,9 +18,16 @@ module Berkshelf
|
|
18
18
|
#
|
19
19
|
# @param [String] cookbook
|
20
20
|
# @param [String] version
|
21
|
-
# @param [
|
22
|
-
def use(cookbook, version,
|
23
|
-
|
21
|
+
# @param [~Location] location
|
22
|
+
def use(cookbook, version, location = nil)
|
23
|
+
message = "Using #{cookbook} (#{version})"
|
24
|
+
|
25
|
+
if location && location.is_a?(PathLocation)
|
26
|
+
message << ' from metadata' if location.metadata?
|
27
|
+
message << " at '#{location.relative_path}'" unless location.relative_path == '.'
|
28
|
+
end
|
29
|
+
|
30
|
+
Berkshelf.ui.info message
|
24
31
|
end
|
25
32
|
|
26
33
|
# Output a Cookbook upload message using {Berkshelf.ui}
|
@@ -41,11 +41,15 @@ module Berkshelf
|
|
41
41
|
#
|
42
42
|
# @param [String] cookbook
|
43
43
|
# @param [String] version
|
44
|
-
# @param [
|
45
|
-
def use(cookbook, version,
|
44
|
+
# @param [~Location] location
|
45
|
+
def use(cookbook, version, location = nil)
|
46
46
|
cookbooks[cookbook] ||= {}
|
47
47
|
cookbooks[cookbook][:version] = version
|
48
|
-
|
48
|
+
|
49
|
+
if location && location.is_a?(PathLocation)
|
50
|
+
cookbooks[cookbook][:metadata] = true if location.metadata?
|
51
|
+
cookbooks[cookbook][:location] = location.relative_path
|
52
|
+
end
|
49
53
|
end
|
50
54
|
|
51
55
|
# Add a Cookbook upload entry to delayed output
|
data/lib/berkshelf/git.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'buff/shell_out'
|
2
3
|
|
3
4
|
module Berkshelf
|
4
5
|
class Git
|
@@ -9,7 +10,7 @@ module Berkshelf
|
|
9
10
|
HAS_SPACE_RE = %r{\s}.freeze
|
10
11
|
|
11
12
|
class << self
|
12
|
-
include
|
13
|
+
include Buff::ShellOut
|
13
14
|
|
14
15
|
# @overload git(commands)
|
15
16
|
# Shellout to the Git executable on your system with the given commands.
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'kitchen/generator/init'
|
3
|
+
rescue LoadError; end
|
2
4
|
|
3
5
|
module Berkshelf
|
4
6
|
class InitGenerator < BaseGenerator
|
@@ -49,10 +51,12 @@ module Berkshelf
|
|
49
51
|
class_option :cookbook_name,
|
50
52
|
type: :string
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
if defined?(Kitchen::Generator::Init)
|
55
|
+
class_option :skip_test_kitchen,
|
56
|
+
type: :boolean,
|
57
|
+
default: false,
|
58
|
+
desc: 'Skip adding a testing environment to your cookbook'
|
59
|
+
end
|
56
60
|
|
57
61
|
def generate
|
58
62
|
validate_configuration
|
@@ -89,13 +93,15 @@ module Berkshelf
|
|
89
93
|
template 'Gemfile.erb', target.join('Gemfile')
|
90
94
|
end
|
91
95
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
if defined?(Kitchen::Generator::Init)
|
97
|
+
unless options[:skip_test_kitchen]
|
98
|
+
# Temporarily use Dir.chdir to ensure the destionation_root of test kitchen's generator
|
99
|
+
# is where we expect until this bug can be addressed:
|
100
|
+
# https://github.com/opscode/test-kitchen/pull/140
|
101
|
+
Dir.chdir target do
|
102
|
+
# Kitchen::Generator::Init.new([], {}, destination_root: target).invoke_all
|
103
|
+
Kitchen::Generator::Init.new([], {}).invoke_all
|
104
|
+
end
|
99
105
|
end
|
100
106
|
end
|
101
107
|
|
data/lib/berkshelf/location.rb
CHANGED
@@ -134,11 +134,6 @@ module Berkshelf
|
|
134
134
|
raise AbstractFunction
|
135
135
|
end
|
136
136
|
|
137
|
-
# @return [Boolean]
|
138
|
-
def downloaded?
|
139
|
-
@downloaded_status
|
140
|
-
end
|
141
|
-
|
142
137
|
# Ensure the retrieved CachedCookbook is valid
|
143
138
|
#
|
144
139
|
# @param [CachedCookbook] cached_cookbook
|
@@ -170,15 +165,10 @@ module Berkshelf
|
|
170
165
|
def to_json(options = {})
|
171
166
|
JSON.pretty_generate(to_hash, options)
|
172
167
|
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
def set_downloaded_status(state)
|
177
|
-
@downloaded_status = state
|
178
|
-
end
|
179
168
|
end
|
180
169
|
end
|
181
170
|
|
182
|
-
|
183
|
-
|
184
|
-
|
171
|
+
require_relative 'locations/chef_api_location'
|
172
|
+
require_relative 'locations/git_location'
|
173
|
+
require_relative 'locations/github_location'
|
174
|
+
require_relative 'locations/site_location'
|
@@ -54,7 +54,7 @@ module Berkshelf
|
|
54
54
|
# @return [Berkshelf::CachedCookbook]
|
55
55
|
def download(destination)
|
56
56
|
if cached?(destination)
|
57
|
-
@ref
|
57
|
+
@ref ||= Berkshelf::Git.rev_parse(revision_path(destination))
|
58
58
|
return local_revision(destination)
|
59
59
|
end
|
60
60
|
|
@@ -77,7 +77,6 @@ module Berkshelf
|
|
77
77
|
cached = CachedCookbook.from_store_path(cb_path)
|
78
78
|
validate_cached(cached)
|
79
79
|
|
80
|
-
set_downloaded_status(true)
|
81
80
|
cached
|
82
81
|
end
|
83
82
|
|
@@ -22,6 +22,7 @@ module Berkshelf
|
|
22
22
|
include Location
|
23
23
|
|
24
24
|
set_location_key :path
|
25
|
+
set_valid_options :path, :metadata
|
25
26
|
|
26
27
|
attr_accessor :path
|
27
28
|
attr_reader :name
|
@@ -30,26 +31,49 @@ module Berkshelf
|
|
30
31
|
# @param [Solve::Constraint] version_constraint
|
31
32
|
# @param [Hash] options
|
32
33
|
#
|
33
|
-
# @option options [
|
34
|
+
# @option options [#to_s] :path
|
34
35
|
# a filepath to the cookbook on your local disk
|
36
|
+
# @option options [Boolean] :metadata
|
37
|
+
# true if this is a metadata source
|
35
38
|
def initialize(name, version_constraint, options = {})
|
36
39
|
@name = name
|
37
40
|
@version_constraint = version_constraint
|
38
|
-
@path = options[:path]
|
39
|
-
|
41
|
+
@path = options[:path].to_s
|
42
|
+
@metadata = options[:metadata]
|
40
43
|
end
|
41
44
|
|
42
|
-
#
|
45
|
+
# The cookbook associated with this path location.
|
43
46
|
#
|
44
47
|
# @return [Berkshelf::CachedCookbook]
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
# the cached cookbook for this location
|
49
|
+
def cookbook
|
50
|
+
@cookbook ||= CachedCookbook.from_path(path, name: name)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns true if the location is a metadata location. By default, no
|
54
|
+
# locations are the metadata location.
|
55
|
+
#
|
56
|
+
# @return [Boolean]
|
57
|
+
def metadata?
|
58
|
+
!!@metadata
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return this PathLocation's path relative to the given target.
|
62
|
+
#
|
63
|
+
# @param [#to_s] target
|
64
|
+
# the path to a file or directory to be relative to
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
# the relative path relative to the target
|
68
|
+
def relative_path(target = '.')
|
69
|
+
my_path = Pathname.new(path).expand_path
|
70
|
+
target_path = Pathname.new(target.to_s).expand_path
|
71
|
+
target_path = target_path.dirname if target_path.file?
|
72
|
+
|
73
|
+
new_path = my_path.relative_path_from(target_path).to_s
|
48
74
|
|
49
|
-
|
50
|
-
|
51
|
-
rescue IOError
|
52
|
-
raise Berkshelf::CookbookNotFound
|
75
|
+
return new_path if new_path.index('.') == 0
|
76
|
+
"./#{new_path}"
|
53
77
|
end
|
54
78
|
|
55
79
|
def to_hash
|
data/lib/berkshelf/resolver.rb
CHANGED
@@ -85,7 +85,7 @@ module Berkshelf
|
|
85
85
|
# @return [Array<Berkshelf::CookbookSource>]
|
86
86
|
# an array of CookbookSources that are currently added to this resolver
|
87
87
|
def sources
|
88
|
-
@sources.
|
88
|
+
@sources.values
|
89
89
|
end
|
90
90
|
|
91
91
|
# Finds a solution for the currently added sources and their dependencies and
|
@@ -153,24 +153,28 @@ module Berkshelf
|
|
153
153
|
#
|
154
154
|
# @return [Boolean]
|
155
155
|
def use_source(source)
|
156
|
+
name = source.name
|
157
|
+
constraint = source.version_constraint
|
158
|
+
location = source.location
|
159
|
+
|
156
160
|
if source.downloaded?
|
157
161
|
cached = source.cached_cookbook
|
158
|
-
|
162
|
+
location.validate_cached(cached)
|
163
|
+
Berkshelf.formatter.use(name, cached.version, location)
|
164
|
+
true
|
165
|
+
elsif location.is_a?(GitLocation)
|
166
|
+
false
|
159
167
|
else
|
160
|
-
|
161
|
-
|
168
|
+
cached = downloader.cookbook_store.satisfy(name, constraint)
|
169
|
+
|
170
|
+
if cached
|
171
|
+
get_source(source).cached_cookbook = cached
|
172
|
+
Berkshelf.formatter.use(name, cached.version)
|
173
|
+
true
|
174
|
+
else
|
175
|
+
false
|
162
176
|
end
|
163
|
-
|
164
|
-
cached = downloader.cookbook_store.satisfy(source.name, source.version_constraint)
|
165
|
-
return false if cached.nil?
|
166
|
-
|
167
|
-
get_source(source).cached_cookbook = cached
|
168
177
|
end
|
169
|
-
|
170
|
-
path = source.location.is_a?(PathLocation) ? source.location.to_s : nil
|
171
|
-
Berkshelf.formatter.use(cached.cookbook_name, cached.version, path)
|
172
|
-
|
173
|
-
true
|
174
178
|
end
|
175
179
|
end
|
176
180
|
end
|
data/lib/berkshelf/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
site :opscode
|
@@ -129,8 +129,8 @@ describe Berkshelf::Berksfile do
|
|
129
129
|
|
130
130
|
before { Dir.chdir(path) }
|
131
131
|
|
132
|
-
it 'sends the add_source message with
|
133
|
-
subject.should_receive(:add_source).with('example_cookbook',
|
132
|
+
it 'sends the add_source message with no version constraint, the path to the cookbook, and the metadata definition' do
|
133
|
+
subject.should_receive(:add_source).with('example_cookbook', nil, path: path.to_s, metadata: true)
|
134
134
|
subject.metadata
|
135
135
|
end
|
136
136
|
end
|
@@ -572,4 +572,32 @@ describe Berkshelf::Berksfile do
|
|
572
572
|
end
|
573
573
|
end
|
574
574
|
end
|
575
|
+
|
576
|
+
describe '#validate_files!' do
|
577
|
+
before { described_class.send(:public, :validate_files!) }
|
578
|
+
let(:cookbook) { double('cookbook', cookbook_name: 'cookbook', path: 'path') }
|
579
|
+
|
580
|
+
it 'raises an error when the cookbook has spaces in the files' do
|
581
|
+
Dir.stub(:glob).and_return(['/there are/spaces/in this/recipes/default.rb'])
|
582
|
+
expect {
|
583
|
+
subject.validate_files!(cookbook)
|
584
|
+
}.to raise_error(Berkshelf::InvalidCookbookFiles)
|
585
|
+
end
|
586
|
+
|
587
|
+
it 'does not raise an error when the cookbook is valid' do
|
588
|
+
Dir.stub(:glob).and_return(['/there-are/no-spaces/in-this/recipes/default.rb'])
|
589
|
+
expect {
|
590
|
+
subject.validate_files!(cookbook)
|
591
|
+
}.to_not raise_error(Berkshelf::InvalidCookbookFiles)
|
592
|
+
end
|
593
|
+
|
594
|
+
it 'does not raise an exception with spaces in the path' do
|
595
|
+
Dir.stub(:glob).and_return(['/there are/spaces/in this/recipes/default.rb'])
|
596
|
+
Pathname.any_instance.stub(:dirname).and_return('/there are/spaces/in this')
|
597
|
+
|
598
|
+
expect {
|
599
|
+
subject.validate_files!(cookbook)
|
600
|
+
}.to_not raise_error
|
601
|
+
end
|
602
|
+
end
|
575
603
|
end
|
@@ -5,21 +5,59 @@ describe Berkshelf::CommunityREST, vcr: { record: :new_episodes, serialize_with:
|
|
5
5
|
let(:target) { '/foo/bar' }
|
6
6
|
let(:destination) { '/destination/bar' }
|
7
7
|
let(:file) { double('file') }
|
8
|
-
let(:gzip_reader) { double('gzip_reader') }
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
describe 'a tar.gz file' do
|
10
|
+
let(:gzip_reader) { double('gzip_reader') }
|
11
|
+
|
12
|
+
before do
|
13
|
+
File.stub(:open).with(target, 'rb').and_return(file)
|
14
|
+
Zlib::GzipReader.stub(:new).with(file).and_return(gzip_reader)
|
15
|
+
Archive::Tar::Minitar.stub(:unpack).with(gzip_reader, destination)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'unpacks the file' do
|
19
|
+
File.should_receive(:open).with(target, 'rb')
|
20
|
+
::IO.should_receive(:binread).with(target, 2).and_return([0x1F, 0x8B].pack("C*"))
|
21
|
+
Zlib::GzipReader.should_receive(:new).with(file)
|
22
|
+
Archive::Tar::Minitar.should_receive(:unpack).with(gzip_reader, destination)
|
23
|
+
|
24
|
+
expect(Berkshelf::CommunityREST.unpack(target, destination)).to eq(destination)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'a tar file' do
|
29
|
+
before do
|
30
|
+
File.stub(:open).with(target, 'rb').and_return(file)
|
31
|
+
Archive::Tar::Minitar.stub(:unpack).with(target, destination)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'unpacks the file' do
|
35
|
+
::IO.should_receive(:binread).once
|
36
|
+
::IO.should_receive(:binread).with(target, 8, 257).and_return("ustar\x0000")
|
37
|
+
Archive::Tar::Minitar.should_receive(:unpack).with(target, destination)
|
38
|
+
|
39
|
+
expect(Berkshelf::CommunityREST.unpack(target, destination)).to eq(destination)
|
40
|
+
end
|
14
41
|
end
|
15
42
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
43
|
+
describe 'a tar.bz2 file' do
|
44
|
+
let(:bzip2_reader) { double('bzip2_reader') }
|
45
|
+
|
46
|
+
before do
|
47
|
+
File.stub(:open).with(target, 'rb').and_return(file)
|
48
|
+
RBzip2::Decompressor.stub(:new).with(file).and_return(bzip2_reader)
|
49
|
+
Archive::Tar::Minitar.stub(:unpack).with(bzip2_reader, destination)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'unpacks the file' do
|
53
|
+
File.should_receive(:open).with(target, 'rb')
|
54
|
+
::IO.should_receive(:binread).twice
|
55
|
+
::IO.should_receive(:binread).with(target, 3).and_return('BZh')
|
56
|
+
RBzip2::Decompressor.should_receive(:new).with(file)
|
57
|
+
Archive::Tar::Minitar.should_receive(:unpack).with(bzip2_reader, destination)
|
21
58
|
|
22
|
-
|
59
|
+
expect(Berkshelf::CommunityREST.unpack(target, destination)).to eq(destination)
|
60
|
+
end
|
23
61
|
end
|
24
62
|
end
|
25
63
|
|