berkshelf 2.0.1 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/berkshelf.gemspec +1 -1
- data/features/upload_command.feature +31 -0
- data/lib/berkshelf.rb +5 -5
- data/lib/berkshelf/berksfile.rb +16 -28
- data/lib/berkshelf/cookbook_generator.rb +10 -2
- data/lib/berkshelf/errors.rb +16 -2
- data/lib/berkshelf/git.rb +6 -7
- data/lib/berkshelf/mixin.rb +7 -0
- data/lib/berkshelf/mixin/dsl_eval.rb +58 -0
- data/lib/berkshelf/thor_ext.rb +3 -0
- data/lib/{thor/monkies → berkshelf/thor_ext}/hash_with_indifferent_access.rb +0 -0
- data/lib/{thor/monkies → berkshelf/thor_ext}/shell.rb +0 -0
- data/lib/berkshelf/version.rb +1 -1
- data/spec/unit/berkshelf/berksfile_spec.rb +20 -26
- data/spec/unit/berkshelf/cookbook_generator_spec.rb +10 -0
- data/spec/unit/berkshelf/mixin/dsl_eval_spec.rb +55 -0
- metadata +11 -9
- data/lib/berkshelf/command.rb +0 -116
- data/lib/berkshelf/mixin/shellout.rb +0 -71
- data/lib/thor/monkies.rb +0 -3
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# 2.0.3
|
2
|
+
|
3
|
+
* Fix issue where groups defined in the Berksfile would not be evaluated
|
4
|
+
|
5
|
+
# 2.0.2
|
6
|
+
|
7
|
+
* Fix issue with shellout on Windows. This would effect uploads and downloads of cookbooks using the Git location.
|
8
|
+
* The Berksfile DSL now evaluates in a clean room to prevent end-users from calling restricted methods.
|
9
|
+
* Fix issue with `berks upload -D` not properly skipping dependencies
|
10
|
+
* Added friendly error message when an unknown license is chosen during cookbook generation
|
11
|
+
|
1
12
|
# 2.0.1
|
2
13
|
|
3
14
|
* Improve performance of `berks upload`. It will now properly respect the Lockfile
|
data/berkshelf.gemspec
CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
s.add_dependency 'hashie', '>= 2.0.2'
|
39
39
|
s.add_dependency 'minitar', '~> 0.5.4'
|
40
40
|
s.add_dependency 'retryable', '~> 1.3.3'
|
41
|
-
s.add_dependency 'ridley', '~> 1.0.
|
41
|
+
s.add_dependency 'ridley', '~> 1.0.2'
|
42
42
|
s.add_dependency 'solve', '>= 0.4.4'
|
43
43
|
s.add_dependency 'test-kitchen', '>= 1.0.0.alpha7'
|
44
44
|
s.add_dependency 'thor', '~> 0.18.0'
|
@@ -263,3 +263,34 @@ Feature: Uploading cookbooks to a Chef Server
|
|
263
263
|
The cookbook 'cookbook with spaces' has invalid filenames:
|
264
264
|
"""
|
265
265
|
And the CLI should exit with the status code for error "InvalidCookbookFiles"
|
266
|
+
|
267
|
+
@chef_server @slow_process
|
268
|
+
Scenario: With the --skip-dependencies flag
|
269
|
+
Given the cookbook store has the cookbooks:
|
270
|
+
| fake | 1.0.0 |
|
271
|
+
| ekaf | 2.0.0 |
|
272
|
+
And the cookbook store contains a cookbook "reset" "3.4.5" with dependencies:
|
273
|
+
| fake | ~> 1.0.0 |
|
274
|
+
And I write to "Berksfile" with:
|
275
|
+
"""
|
276
|
+
cookbook 'fake', '1.0.0'
|
277
|
+
cookbook 'ekaf', '2.0.0'
|
278
|
+
cookbook 'reset', '3.4.5'
|
279
|
+
"""
|
280
|
+
And the Chef server does not have the cookbooks:
|
281
|
+
| fake | 1.0.0 |
|
282
|
+
| ekaf | 2.0.0 |
|
283
|
+
| reset | 3.4.5 |
|
284
|
+
When I successfully run `berks upload reset -D`
|
285
|
+
Then the output should contain:
|
286
|
+
"""
|
287
|
+
Uploading reset (3.4.5) to: 'http://localhost:4000/'
|
288
|
+
Uploading fake (1.0.0) to: 'http://localhost:4000/'
|
289
|
+
"""
|
290
|
+
And the Chef server should have the cookbooks:
|
291
|
+
| reset | 3.4.5 |
|
292
|
+
| fake | 1.0.0 |
|
293
|
+
And the Chef server should not have the cookbooks:
|
294
|
+
| ekaf | 2.0.0 |
|
295
|
+
And the exit status should be 0
|
296
|
+
|
data/lib/berkshelf.rb
CHANGED
@@ -14,9 +14,10 @@ require 'tmpdir'
|
|
14
14
|
require 'uri'
|
15
15
|
require 'zlib'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
require_relative 'berkshelf/core_ext'
|
18
|
+
require_relative 'berkshelf/errors'
|
19
|
+
require_relative 'berkshelf/mixin'
|
20
|
+
require_relative 'berkshelf/thor_ext'
|
20
21
|
|
21
22
|
JSON.create_id = nil
|
22
23
|
|
@@ -24,7 +25,6 @@ module Berkshelf
|
|
24
25
|
DEFAULT_FILENAME = 'Berksfile'.freeze
|
25
26
|
|
26
27
|
class << self
|
27
|
-
require 'berkshelf/mixin/logging'
|
28
28
|
include Berkshelf::Mixin::Logging
|
29
29
|
|
30
30
|
attr_accessor :ui
|
@@ -160,4 +160,4 @@ require_relative 'berkshelf/ui'
|
|
160
160
|
require_relative 'berkshelf/version'
|
161
161
|
|
162
162
|
Ridley.logger = Celluloid.logger = Berkshelf.logger = Logger.new(STDOUT)
|
163
|
-
Berkshelf.logger.level = Logger::WARN
|
163
|
+
Berkshelf.logger.level = Logger::WARN
|
data/lib/berkshelf/berksfile.rb
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
module Berkshelf
|
2
2
|
class Berksfile
|
3
|
-
require 'berkshelf/mixin/logging'
|
4
|
-
include Berkshelf::Mixin::Logging
|
5
|
-
|
6
|
-
extend Forwardable
|
7
|
-
|
8
3
|
class << self
|
9
|
-
# @param [
|
4
|
+
# @param [#to_s] file
|
10
5
|
# a path on disk to a Berksfile to instantiate from
|
11
6
|
#
|
12
7
|
# @return [Berksfile]
|
13
8
|
def from_file(file)
|
14
|
-
|
15
|
-
|
16
|
-
object.load(content)
|
17
|
-
rescue Errno::ENOENT => e
|
9
|
+
new(file).dsl_eval_file(file)
|
10
|
+
rescue Errno::ENOENT => ex
|
18
11
|
raise BerksfileNotFound, "No Berksfile or Berksfile.lock found at: #{file}"
|
12
|
+
rescue => ex
|
13
|
+
raise BerksfileReadError.new(ex)
|
19
14
|
end
|
20
15
|
|
21
16
|
# Copy all cached_cookbooks to the given directory. Each cookbook will be contained in
|
@@ -60,6 +55,16 @@ module Berkshelf
|
|
60
55
|
end
|
61
56
|
end
|
62
57
|
|
58
|
+
include Berkshelf::Mixin::Logging
|
59
|
+
include Berkshelf::Mixin::DSLEval
|
60
|
+
extend Forwardable
|
61
|
+
|
62
|
+
expose_method :metadata
|
63
|
+
expose_method :group
|
64
|
+
expose_method :site
|
65
|
+
expose_method :chef_api
|
66
|
+
expose_method :cookbook
|
67
|
+
|
63
68
|
@@active_group = nil
|
64
69
|
|
65
70
|
# @return [String]
|
@@ -549,7 +554,7 @@ module Berkshelf
|
|
549
554
|
end
|
550
555
|
|
551
556
|
if options[:skip_dependencies]
|
552
|
-
missing_cookbooks = options.fetch(:cookbooks, nil) -
|
557
|
+
missing_cookbooks = options.fetch(:cookbooks, nil) - cached_cookbooks.map(&:cookbook_name)
|
553
558
|
unless missing_cookbooks.empty?
|
554
559
|
msg = "Unable to upload cookbooks: #{missing_cookbooks.sort.join(', ')}\n"
|
555
560
|
msg << "Specified cookbooks must be defined within the Berkshelf file when using the"
|
@@ -681,23 +686,6 @@ module Berkshelf
|
|
681
686
|
{ solution: resolver.resolve, sources: resolver.sources }
|
682
687
|
end
|
683
688
|
|
684
|
-
# Reload this instance of Berksfile with the given content. The content
|
685
|
-
# is a string that may contain terms from the included DSL.
|
686
|
-
#
|
687
|
-
# @param [String] content
|
688
|
-
#
|
689
|
-
# @raise [BerksfileReadError] if Berksfile contains bad content
|
690
|
-
#
|
691
|
-
# @return [Berksfile]
|
692
|
-
def load(content)
|
693
|
-
begin
|
694
|
-
instance_eval(content)
|
695
|
-
rescue => e
|
696
|
-
raise BerksfileReadError.new(e)
|
697
|
-
end
|
698
|
-
self
|
699
|
-
end
|
700
|
-
|
701
689
|
# Get the lockfile corresponding to this Berksfile. This is necessary because
|
702
690
|
# the user can specify a different path to the Berksfile. So assuming the lockfile
|
703
691
|
# is named "Berksfile.lock" is a poor assumption.
|
@@ -2,6 +2,14 @@ module Berkshelf
|
|
2
2
|
class CookbookGenerator < BaseGenerator
|
3
3
|
require_relative 'config'
|
4
4
|
|
5
|
+
LICENSES = [
|
6
|
+
"apachev2",
|
7
|
+
"gplv2",
|
8
|
+
"gplv3",
|
9
|
+
"mit",
|
10
|
+
"reserved"
|
11
|
+
].freeze
|
12
|
+
|
5
13
|
argument :name,
|
6
14
|
type: :string,
|
7
15
|
required: true
|
@@ -79,7 +87,7 @@ module Berkshelf
|
|
79
87
|
when 'mit'; 'MIT'
|
80
88
|
when 'reserved'; 'All rights reserved'
|
81
89
|
else
|
82
|
-
raise Berkshelf::
|
90
|
+
raise Berkshelf::LicenseNotFound.new(options[:license])
|
83
91
|
end
|
84
92
|
end
|
85
93
|
|
@@ -95,7 +103,7 @@ module Berkshelf
|
|
95
103
|
when 'mit'; 'licenses/mit.erb'
|
96
104
|
when 'reserved'; 'licenses/reserved.erb'
|
97
105
|
else
|
98
|
-
raise Berkshelf::
|
106
|
+
raise Berkshelf::LicenseNotFound.new(options[:license])
|
99
107
|
end
|
100
108
|
end
|
101
109
|
|
data/lib/berkshelf/errors.rb
CHANGED
@@ -185,7 +185,6 @@ module Berkshelf
|
|
185
185
|
|
186
186
|
class ConfigExists < BerkshelfError; status_code(116); end
|
187
187
|
class ConfigurationError < BerkshelfError; status_code(117); end
|
188
|
-
class CommandUnsuccessful < BerkshelfError; status_code(118); end
|
189
188
|
class InsufficientPrivledges < BerkshelfError; status_code(119); end
|
190
189
|
class ExplicitCookbookNotFound < BerkshelfError; status_code(120); end
|
191
190
|
class ValidationFailed < BerkshelfError; status_code(121); end
|
@@ -340,10 +339,25 @@ module Berkshelf
|
|
340
339
|
end
|
341
340
|
end
|
342
341
|
|
342
|
+
class LicenseNotFound < BerkshelfError
|
343
|
+
status_code(134)
|
344
|
+
|
345
|
+
attr_reader :license
|
346
|
+
|
347
|
+
def initialize(license)
|
348
|
+
@license = license
|
349
|
+
end
|
350
|
+
|
351
|
+
def to_s
|
352
|
+
"Unknown license: '#{license}'\n" +
|
353
|
+
"Available licenses: #{Berkshelf::CookbookGenerator::LICENSES.join(', ')}"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
343
357
|
# Raised when a cookbook or its recipes contain a space or invalid
|
344
358
|
# character in the path.
|
345
359
|
class ConfigNotFound < BerkshelfError
|
346
|
-
status_code(
|
360
|
+
status_code(135)
|
347
361
|
|
348
362
|
# @param [String] type
|
349
363
|
# the type of config that was not found (Berkshelf, Chef, etc)
|
data/lib/berkshelf/git.rb
CHANGED
@@ -2,9 +2,6 @@ require 'uri'
|
|
2
2
|
|
3
3
|
module Berkshelf
|
4
4
|
class Git
|
5
|
-
require 'berkshelf/mixin/shellout'
|
6
|
-
extend Berkshelf::Mixin::Shellout
|
7
|
-
|
8
5
|
GIT_REGEXP = URI.regexp(%w(http https ssh git+ssh git rsync))
|
9
6
|
SCP_REGEXP = /^(.+@)?[\w\d\.-]+:.*$/
|
10
7
|
|
@@ -12,6 +9,8 @@ module Berkshelf
|
|
12
9
|
HAS_SPACE_RE = %r{\s}.freeze
|
13
10
|
|
14
11
|
class << self
|
12
|
+
include Ridley::Mixin::ShellOut
|
13
|
+
|
15
14
|
# @overload git(commands)
|
16
15
|
# Shellout to the Git executable on your system with the given commands.
|
17
16
|
#
|
@@ -22,13 +21,13 @@ module Berkshelf
|
|
22
21
|
def git(*command)
|
23
22
|
command.unshift(git_cmd)
|
24
23
|
command_str = command.map { |p| quote_cmd_arg(p) }.join(' ')
|
25
|
-
|
24
|
+
response = shell_out(command_str)
|
26
25
|
|
27
|
-
unless
|
28
|
-
raise GitError.new(
|
26
|
+
unless response.success?
|
27
|
+
raise GitError.new(response.stderr.strip)
|
29
28
|
end
|
30
29
|
|
31
|
-
|
30
|
+
response.stdout.strip
|
32
31
|
end
|
33
32
|
|
34
33
|
# Clone a remote Git repository to disk
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Berkshelf
|
2
|
+
module Mixin
|
3
|
+
module DSLEval
|
4
|
+
class CleanRoom
|
5
|
+
attr_reader :instance
|
6
|
+
|
7
|
+
def initialize(instance)
|
8
|
+
@instance = instance
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def included(base)
|
14
|
+
base.send(:extend, ClassMethods)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def clean_room
|
20
|
+
@clean_room ||= begin
|
21
|
+
exposed_methods = self.exposed_methods
|
22
|
+
|
23
|
+
Class.new(DSLEval::CleanRoom) do
|
24
|
+
exposed_methods.each do |exposed_method|
|
25
|
+
define_method(exposed_method) do |*args, &block|
|
26
|
+
instance.send(exposed_method, *args, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def expose_method(method)
|
34
|
+
exposed_methods << method.to_sym
|
35
|
+
end
|
36
|
+
|
37
|
+
def exposed_methods
|
38
|
+
@exposed_methods ||= Array.new
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Object]
|
43
|
+
def dsl_eval(&block)
|
44
|
+
self.class.clean_room.new(self).instance_eval(&block)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param [String] filepath
|
49
|
+
#
|
50
|
+
# @return [Object]
|
51
|
+
def dsl_eval_file(filepath)
|
52
|
+
filepath = filepath.to_s
|
53
|
+
contents = File.read(filepath)
|
54
|
+
dsl_eval { eval(contents, binding, filepath, 1) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
File without changes
|
File without changes
|
data/lib/berkshelf/version.rb
CHANGED
@@ -2,10 +2,27 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Berkshelf::Berksfile do
|
4
4
|
describe '.from_file' do
|
5
|
-
let(:
|
5
|
+
let(:content) do
|
6
|
+
<<-EOF.strip
|
7
|
+
cookbook 'ntp', '<= 1.0.0'
|
8
|
+
cookbook 'mysql'
|
9
|
+
cookbook 'nginx', '< 0.101.2'
|
10
|
+
cookbook 'ssh_known_hosts2', :git => 'https://github.com/erikh/chef-ssh_known_hosts2.git'
|
11
|
+
EOF
|
12
|
+
end
|
13
|
+
let(:berksfile) { tmp_path.join('Berksfile') }
|
6
14
|
|
7
|
-
|
8
|
-
|
15
|
+
before { File.open(berksfile, 'w+') { |f| f.write(content) } }
|
16
|
+
subject(:from_file) { described_class.from_file(berksfile) }
|
17
|
+
|
18
|
+
it "reads the content of the Berksfile and binds them to a new instance" do
|
19
|
+
%w(ntp mysql nginx ssh_known_hosts2).each do |name|
|
20
|
+
expect(subject).to have_source(name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns an instance of Berkshelf::Berksfile" do
|
25
|
+
expect(subject).to be_a(described_class)
|
9
26
|
end
|
10
27
|
|
11
28
|
context 'when Berksfile does not exist at given path' do
|
@@ -340,29 +357,6 @@ describe Berkshelf::Berksfile do
|
|
340
357
|
end
|
341
358
|
end
|
342
359
|
|
343
|
-
describe '#load' do
|
344
|
-
let(:content) do
|
345
|
-
<<-EOF.strip
|
346
|
-
cookbook 'ntp', '<= 1.0.0'
|
347
|
-
cookbook 'mysql'
|
348
|
-
cookbook 'nginx', '< 0.101.2'
|
349
|
-
cookbook 'ssh_known_hosts2', :git => 'https://github.com/erikh/chef-ssh_known_hosts2.git'
|
350
|
-
EOF
|
351
|
-
end
|
352
|
-
|
353
|
-
it 'reads the content of a Berksfile and adds the sources to the Shelf' do
|
354
|
-
subject.load(content)
|
355
|
-
|
356
|
-
%w(ntp mysql nginx ssh_known_hosts2).each do |name|
|
357
|
-
expect(subject).to have_source(name)
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
it 'returns an instance of Berksfile' do
|
362
|
-
expect(subject.load(content)).to be_a(Berkshelf::Berksfile)
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
360
|
describe '#add_source' do
|
367
361
|
let(:name) { 'cookbook_one' }
|
368
362
|
let(:constraint) { '= 1.2.0' }
|
@@ -77,4 +77,14 @@ describe Berkshelf::CookbookGenerator do
|
|
77
77
|
}
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
context "given an invalid option for :license" do
|
82
|
+
subject(:run) do
|
83
|
+
capture(:stdout) { described_class.new([target, name], license: 'not-there').invoke_all }
|
84
|
+
end
|
85
|
+
|
86
|
+
it "raises a LicenseNotFound error" do
|
87
|
+
expect { run }.to raise_error(Berkshelf::LicenseNotFound)
|
88
|
+
end
|
89
|
+
end
|
80
90
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Berkshelf::Mixin::DSLEval do
|
4
|
+
let(:klass) do
|
5
|
+
klass = Class.new
|
6
|
+
klass.send(:include, described_class)
|
7
|
+
klass
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "ClassMethods" do
|
11
|
+
describe "::clean_room" do
|
12
|
+
subject { klass.clean_room }
|
13
|
+
|
14
|
+
it "returns an anonymous class inheriting from DSLEval::CleanRoom" do
|
15
|
+
expect(subject.superclass).to eql(described_class::CleanRoom)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "::expose_method" do
|
20
|
+
subject { klass }
|
21
|
+
|
22
|
+
it "adds a method to the exposed methods" do
|
23
|
+
klass.expose_method(:something)
|
24
|
+
expect(subject.exposed_methods).to have(1).item
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "::exposed_methods" do
|
29
|
+
it "returns an array" do
|
30
|
+
expect(klass.exposed_methods).to be_a(Array)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#dsl_eval" do
|
36
|
+
subject do
|
37
|
+
klass.new.dsl_eval { }
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns an instance of the including class" do
|
41
|
+
expect(subject).to be_a(klass)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#dsl_eval_file" do
|
46
|
+
let(:filepath) { tmp_path.join('somefile') }
|
47
|
+
before { FileUtils.touch(filepath) }
|
48
|
+
|
49
|
+
subject { klass.new.dsl_eval_file(filepath) }
|
50
|
+
|
51
|
+
it "returns an instance of the including class" do
|
52
|
+
expect(subject).to be_a(klass)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
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: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-06-
|
16
|
+
date: 2013-06-11 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activesupport
|
@@ -150,7 +150,7 @@ dependencies:
|
|
150
150
|
requirements:
|
151
151
|
- - ~>
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version: 1.0.
|
153
|
+
version: 1.0.2
|
154
154
|
type: :runtime
|
155
155
|
prerelease: false
|
156
156
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -158,7 +158,7 @@ dependencies:
|
|
158
158
|
requirements:
|
159
159
|
- - ~>
|
160
160
|
- !ruby/object:Gem::Version
|
161
|
-
version: 1.0.
|
161
|
+
version: 1.0.2
|
162
162
|
- !ruby/object:Gem::Dependency
|
163
163
|
name: solve
|
164
164
|
requirement: !ruby/object:Gem::Requirement
|
@@ -579,7 +579,6 @@ files:
|
|
579
579
|
- lib/berkshelf/chef/cookbook.rb
|
580
580
|
- lib/berkshelf/chef/cookbook/chefignore.rb
|
581
581
|
- lib/berkshelf/cli.rb
|
582
|
-
- lib/berkshelf/command.rb
|
583
582
|
- lib/berkshelf/commands/shelf.rb
|
584
583
|
- lib/berkshelf/commands/test_command.rb
|
585
584
|
- lib/berkshelf/community_rest.rb
|
@@ -608,17 +607,18 @@ files:
|
|
608
607
|
- lib/berkshelf/locations/site_location.rb
|
609
608
|
- lib/berkshelf/lockfile.rb
|
610
609
|
- lib/berkshelf/logger.rb
|
610
|
+
- lib/berkshelf/mixin.rb
|
611
611
|
- lib/berkshelf/mixin/config.rb
|
612
|
+
- lib/berkshelf/mixin/dsl_eval.rb
|
612
613
|
- lib/berkshelf/mixin/logging.rb
|
613
|
-
- lib/berkshelf/mixin/shellout.rb
|
614
614
|
- lib/berkshelf/resolver.rb
|
615
615
|
- lib/berkshelf/test.rb
|
616
616
|
- lib/berkshelf/thor.rb
|
617
|
+
- lib/berkshelf/thor_ext.rb
|
618
|
+
- lib/berkshelf/thor_ext/hash_with_indifferent_access.rb
|
619
|
+
- lib/berkshelf/thor_ext/shell.rb
|
617
620
|
- lib/berkshelf/ui.rb
|
618
621
|
- lib/berkshelf/version.rb
|
619
|
-
- lib/thor/monkies.rb
|
620
|
-
- lib/thor/monkies/hash_with_indifferent_access.rb
|
621
|
-
- lib/thor/monkies/shell.rb
|
622
622
|
- spec/config/berkshelf.pem
|
623
623
|
- spec/config/knife.rb
|
624
624
|
- spec/config/validator.pem
|
@@ -693,6 +693,7 @@ files:
|
|
693
693
|
- spec/unit/berkshelf/locations/site_location_spec.rb
|
694
694
|
- spec/unit/berkshelf/lockfile_spec.rb
|
695
695
|
- spec/unit/berkshelf/logger_spec.rb
|
696
|
+
- spec/unit/berkshelf/mixin/dsl_eval_spec.rb
|
696
697
|
- spec/unit/berkshelf/mixin/logging_spec.rb
|
697
698
|
- spec/unit/berkshelf/resolver_spec.rb
|
698
699
|
- spec/unit/berkshelf/ui_spec.rb
|
@@ -830,6 +831,7 @@ test_files:
|
|
830
831
|
- spec/unit/berkshelf/locations/site_location_spec.rb
|
831
832
|
- spec/unit/berkshelf/lockfile_spec.rb
|
832
833
|
- spec/unit/berkshelf/logger_spec.rb
|
834
|
+
- spec/unit/berkshelf/mixin/dsl_eval_spec.rb
|
833
835
|
- spec/unit/berkshelf/mixin/logging_spec.rb
|
834
836
|
- spec/unit/berkshelf/resolver_spec.rb
|
835
837
|
- spec/unit/berkshelf/ui_spec.rb
|
data/lib/berkshelf/command.rb
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
module Berkshelf
|
2
|
-
# This superclass is responsible for handling common command methods and options.
|
3
|
-
module Command
|
4
|
-
# Initialize a new instance of the parent class
|
5
|
-
#
|
6
|
-
# @param [Hash] options
|
7
|
-
# the list of options to pass to the installer
|
8
|
-
def initialize(options = {})
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
# Validate the options hash, ensuring there are no conflicting arguments
|
15
|
-
#
|
16
|
-
# @raise [Berkshelf::ArgumentError]
|
17
|
-
# if there are conflicting or invalid options
|
18
|
-
def validate_options!
|
19
|
-
if options[:except] && options[:only]
|
20
|
-
raise Berkshelf::ArgumentError, 'Cannot specify both :except and :only'
|
21
|
-
end
|
22
|
-
|
23
|
-
if options[:cookbooks] && (options[:except] || options[:only])
|
24
|
-
Berkshelf.ui.warn ':cookbooks were supplied to update(), so :except and :only are ignored...'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Ensure the berkshelf directory is created and accessible.
|
29
|
-
def ensure_berkshelf_directory!
|
30
|
-
unless File.exists?(Berkshelf.berkshelf_path)
|
31
|
-
FileUtils.mkdir_p(Berkshelf.berkshelf_path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Check for the presence of a Berksfile. Berkshelf cannot do anything
|
36
|
-
# without the presence of a Berksfile.lock.
|
37
|
-
def ensure_berksfile!
|
38
|
-
unless File.exists?(options[:berksfile])
|
39
|
-
raise Berkshelf::BerksfileNotFound, "No #{options[:berksfile]} was found at ."
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Check that the Berksfile has content. If the Berksfile is empty, raise
|
44
|
-
# an exception to require at least one definition.
|
45
|
-
def ensure_berksfile_content!
|
46
|
-
begin
|
47
|
-
unless File.read(options[:berksfile]).size > 1
|
48
|
-
raise Berkshelf::BerksfileNotFound, "Your #{options[:berksfile]} is empty! You need at least one cookbook definition."
|
49
|
-
end
|
50
|
-
rescue Errno::ENOENT
|
51
|
-
ensure_berksfile!
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# @return [Hash]
|
56
|
-
# the options for this installer
|
57
|
-
def options
|
58
|
-
@options ||= {}
|
59
|
-
end
|
60
|
-
|
61
|
-
# Attempt to load and parse the lockfile associated with this berksfile.
|
62
|
-
#
|
63
|
-
# @return [Berkshelf::Lockfile, nil]
|
64
|
-
# the lockfile for the current berksfile
|
65
|
-
def lockfile
|
66
|
-
@lockfile ||= berksfile.lockfile
|
67
|
-
end
|
68
|
-
|
69
|
-
# Load the Berksfile for the current project.
|
70
|
-
#
|
71
|
-
# @raise [Berkshelf::BerksfileNotFound]
|
72
|
-
# if the file is not found
|
73
|
-
#
|
74
|
-
# @return [Berkshelf::Berksfile]
|
75
|
-
# the current Berksfile
|
76
|
-
def berksfile
|
77
|
-
@berksfile ||= Berkshelf::Berksfile.from_file(options[:berksfile])
|
78
|
-
end
|
79
|
-
|
80
|
-
# Filter the list of sources from the options passed to the installer.
|
81
|
-
#
|
82
|
-
# @param [Array<Berkshelf::CookbookSource>] sources
|
83
|
-
# the list of sources to resolve
|
84
|
-
#
|
85
|
-
# @raise [Berkshelf::ArgumentError]
|
86
|
-
# if a value for both :except and :only is provided
|
87
|
-
#
|
88
|
-
# @raise [Berkshelf::CookbookNotFound]
|
89
|
-
# if a cookbook name is specified that does not exist
|
90
|
-
#
|
91
|
-
# @return [Array<Berkshelf::CookbookSource>]
|
92
|
-
def filter(sources)
|
93
|
-
cookbooks = Array(options[:cookbooks]).map(&:to_s)
|
94
|
-
except = Array(options[:except]).map(&:to_sym)
|
95
|
-
only = Array(options[:only]).map(&:to_sym)
|
96
|
-
|
97
|
-
case
|
98
|
-
when !cookbooks.empty?
|
99
|
-
missing_cookbooks = (cookbooks - sources.map(&:name))
|
100
|
-
|
101
|
-
unless missing_cookbooks.empty?
|
102
|
-
raise Berkshelf::CookbookNotFound, "Could not find cookbooks #{missing_cookbooks.collect{|cookbook| "'#{cookbook}'"}.join(', ')} in any of the sources. #{missing_cookbooks.size == 1 ? 'Is it' : 'Are they' } in your Berksfile?"
|
103
|
-
end
|
104
|
-
|
105
|
-
sources.select { |source| options[:cookbooks].include?(source.name) }
|
106
|
-
when !except.empty?
|
107
|
-
sources.select { |source| (except & source.groups).empty? }
|
108
|
-
when !only.empty?
|
109
|
-
sources.select { |source| !(only & source.groups).empty? }
|
110
|
-
else
|
111
|
-
sources
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
|
3
|
-
module Berkshelf
|
4
|
-
module Mixin
|
5
|
-
module Shellout
|
6
|
-
# Perform a cross-platform shell command, returning the process result.
|
7
|
-
# This uses Process.spawn under the hood for Ruby 1.9, so see
|
8
|
-
# {Process.spawn} for more information.
|
9
|
-
#
|
10
|
-
# On JRuby, a system command is used and $stdout and $stderr are captured.
|
11
|
-
#
|
12
|
-
# @param [String] command
|
13
|
-
# @param [Hash] options
|
14
|
-
# a list of options to send to {Process.spawn}
|
15
|
-
# @return [Hashie::Mash]
|
16
|
-
# information about the command including:
|
17
|
-
# - stderr
|
18
|
-
# - stdout
|
19
|
-
# - exitstatus
|
20
|
-
# - pid
|
21
|
-
# - success?
|
22
|
-
# - failure?
|
23
|
-
def shellout(command)
|
24
|
-
if defined?(RUBY_PLATFORM) && RUBY_PLATFORM == 'java' # jruby
|
25
|
-
out, err, e = capture do
|
26
|
-
system(command)
|
27
|
-
end
|
28
|
-
else
|
29
|
-
begin
|
30
|
-
out_file, err_file = Tempfile.new('berkshelf.stdout'), Tempfile.new('berkshelf.stderr')
|
31
|
-
pid = Process.spawn({}, command, out: out_file.to_i, err: err_file.to_i)
|
32
|
-
Process.waitpid(pid)
|
33
|
-
|
34
|
-
out, err = File.read(out_file), File.read(err_file)
|
35
|
-
e = $?
|
36
|
-
rescue Errno::ENOENT
|
37
|
-
out, err = "", "command not found: #{command}"
|
38
|
-
e = $?
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
Hashie::Mash.new({
|
43
|
-
stdout: out.strip,
|
44
|
-
stderr: err.strip,
|
45
|
-
exitstatus: e.exitstatus,
|
46
|
-
pid: e.pid,
|
47
|
-
success?: e.success?,
|
48
|
-
failure?: !e.success?
|
49
|
-
})
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
# Execute the given block, capturing $stdout, $stderr, and the returned process.
|
54
|
-
#
|
55
|
-
# @return [Array<StringIO, StringIO, Process>]
|
56
|
-
# a tuple of $stdout, $stderr, and the Process
|
57
|
-
def capture(&block)
|
58
|
-
out, err = StringIO.new, StringIO.new
|
59
|
-
$stdout, $stderr = out, err
|
60
|
-
|
61
|
-
yield
|
62
|
-
|
63
|
-
out.rewind
|
64
|
-
err.rewind
|
65
|
-
return out.read, err.read, $?
|
66
|
-
ensure
|
67
|
-
$stdout, $stderr = STDOUT, STDERR
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/thor/monkies.rb
DELETED