poise 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -4
- data/lib/poise/helpers/chefspec_matchers.rb +2 -6
- data/lib/poise/helpers/option_collector.rb +17 -3
- data/lib/poise/utils.rb +13 -3
- data/lib/poise/utils/resource_provider_mixin.rb +23 -11
- data/lib/poise/version.rb +1 -1
- data/test/gemfiles/chef-12.0.gemfile +1 -0
- data/test/gemfiles/chef-12.1.gemfile +1 -0
- data/test/gemfiles/chef-12.2.gemfile +1 -0
- data/test/gemfiles/chef-12.gemfile +1 -0
- data/test/gemfiles/master.gemfile +3 -2
- data/test/spec/helpers/option_collector_spec.rb +44 -0
- data/test/spec/helpers/subresources/container_spec.rb +16 -1
- data/test/spec/utils/resource_provider_mixin_spec.rb +36 -0
- data/test/spec/utils_spec.rb +24 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 139be873d0ca15732ed1e63cda3c64fb5f66df07
|
4
|
+
data.tar.gz: 5c320b061767f73716e12d14cd4435d2ac454ade
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cad8094aa339ae2da67533a14be99ad2ad855f7f9e1896540db99a23a129c714e1cc906e89fa1c46be36a417bc5dfa4b24cf7882d51cfe73b881d1bfb98dabf
|
7
|
+
data.tar.gz: c924334c534a43fc017a2b2437479ff8b1e73460485df2559ebceb750178ec204219a6075185c2194a214b75cf061aeb7f9e714cee8845ee47a6e678fda28915
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v2.0.1
|
4
|
+
|
5
|
+
* Make the ChefspecHelpers helper a no-op if chefspec is not already loaded.
|
6
|
+
* Fix for finding the correct cookbook for a file when using vendored gems.
|
7
|
+
* New flag for the OptionCollector helper, `parser`:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class Resource < Chef::Resource
|
11
|
+
include Poise
|
12
|
+
attribute(:options, option_collector: true, parser: proc {|val| parse(val) })
|
13
|
+
|
14
|
+
def parse(val)
|
15
|
+
{name: val}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
* Fix for a possible infinite loop when using `ResourceProviderMixin` in a nested
|
21
|
+
module structure.
|
22
|
+
|
3
23
|
## v2.0.0
|
4
24
|
|
5
25
|
Major overhaul! Poise is now a Halite gem/cookbook. New helpers:
|
data/Gemfile
CHANGED
@@ -18,13 +18,10 @@ source 'https://rubygems.org/'
|
|
18
18
|
|
19
19
|
gemspec path: File.expand_path('..', __FILE__)
|
20
20
|
|
21
|
-
def dev_gem(name, path: File.join('..', name)
|
22
|
-
github = "#{github}/#{name}" unless github.include?('/')
|
21
|
+
def dev_gem(name, path: File.join('..', name))
|
23
22
|
path = File.expand_path(File.join('..', path), __FILE__)
|
24
23
|
if File.exist?(path)
|
25
24
|
gem name, path: path
|
26
|
-
else
|
27
|
-
gem name, github: github
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
@@ -14,12 +14,8 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
require 'rspec/expectations'
|
20
|
-
rescue LoadError
|
21
|
-
# Don't panic! We will no-op later on if these aren't available.
|
22
|
-
end
|
17
|
+
# Not requiring chefspec or rspec/expectations since this code should only
|
18
|
+
# activate if they are already loaded.
|
23
19
|
|
24
20
|
require 'poise/helpers/lwrp_polyfill'
|
25
21
|
require 'poise/helpers/resource_name'
|
@@ -16,6 +16,8 @@
|
|
16
16
|
|
17
17
|
require 'chef/mash'
|
18
18
|
|
19
|
+
require 'poise/error'
|
20
|
+
|
19
21
|
|
20
22
|
module Poise
|
21
23
|
module Helpers
|
@@ -80,8 +82,12 @@ module Poise
|
|
80
82
|
# Define an option collector attribute. Normally used via {.attribute}.
|
81
83
|
#
|
82
84
|
# @param name [String, Symbol] Name of the attribute to define.
|
83
|
-
# @param default [
|
84
|
-
|
85
|
+
# @param default [Hash] Default value for the options.
|
86
|
+
# @param parser [Proc, Symbol] Optional parser method. If a symbol it is
|
87
|
+
# called as a method on self. Takes a non-hash value and returns a
|
88
|
+
# hash of its parsed representation.
|
89
|
+
def option_collector_attribute(name, default: {}, parser: nil)
|
90
|
+
raise Poise::Error.new("Parser must be a Proc or Symbol: #{parser.inspect}") if parser && !(parser.is_a?(Proc) || parser.is_a?(Symbol))
|
85
91
|
# Unlike LWRPBase.attribute, I don't care about Ruby 1.8. Worlds tiniest violin.
|
86
92
|
define_method(name.to_sym) do |arg=nil, &block|
|
87
93
|
iv_sym = :"@#{name}"
|
@@ -91,7 +97,15 @@ module Poise
|
|
91
97
|
Mash.new(default) # Wrap in a mash because fuck str vs sym.
|
92
98
|
end
|
93
99
|
if arg
|
94
|
-
|
100
|
+
if !arg.is_a?(Hash) && parser
|
101
|
+
arg = case parser
|
102
|
+
when Proc
|
103
|
+
instance_exec(arg, &parser)
|
104
|
+
when Symbol
|
105
|
+
send(parser, arg)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
raise Exceptions::ValidationFailed, "Option #{name} must be a Hash" if !arg.is_a?(Hash)
|
95
109
|
# Should this and the update below be a deep merge?
|
96
110
|
value.update(arg)
|
97
111
|
end
|
data/lib/poise/utils.rb
CHANGED
@@ -36,25 +36,35 @@ module Poise
|
|
36
36
|
# # ...
|
37
37
|
# end
|
38
38
|
def find_cookbook_name(run_context, filename)
|
39
|
+
possibles = {}
|
40
|
+
Chef::Log.debug("[Poise] Checking cookbook for #{filename.inspect}")
|
39
41
|
run_context.cookbook_collection.each do |name, ver|
|
40
42
|
# This special method is added by Halite::Gem#as_cookbook_version.
|
41
43
|
if ver.respond_to?(:halite_root)
|
42
44
|
# The join is there because ../poise-ruby/lib starts with ../poise so
|
43
45
|
# we want a trailing /.
|
46
|
+
Chef::Log.debug("")
|
44
47
|
if filename.start_with?(File.join(ver.halite_root, ''))
|
45
|
-
|
48
|
+
Chef::Log.debug("[Poise] Found matching halite_root in #{name}: #{ver.halite_root.inspect}")
|
49
|
+
possibles[ver.halite_root] = name
|
46
50
|
end
|
47
51
|
else
|
48
52
|
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |seg|
|
49
53
|
ver.segment_filenames(seg).each do |file|
|
54
|
+
# Put this behind an environment variable because it is verbose
|
55
|
+
# even for normal debugging-level output.
|
56
|
+
Chef::Log.debug("[Poise] Checking #{seg} in #{name}: #{file.inspect}") if ENV['POISE_DEBUG']
|
50
57
|
if file == filename
|
51
|
-
|
58
|
+
Chef::Log.debug("[Poise] Found matching #{seg} in #{name}: #{file.inspect}")
|
59
|
+
possibles[file] = name
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
55
63
|
end
|
56
64
|
end
|
57
|
-
raise Poise::Error.new("Unable to find cookbook for file #{filename.inspect}")
|
65
|
+
raise Poise::Error.new("Unable to find cookbook for file #{filename.inspect}") if possibles.empty?
|
66
|
+
# Sort the items by matching path length, pick the name attached to the longest.
|
67
|
+
possibles.sort_by{|key, value| key.length }.last[1]
|
58
68
|
end
|
59
69
|
end
|
60
70
|
end
|
@@ -34,20 +34,32 @@ module Poise
|
|
34
34
|
# end
|
35
35
|
# end
|
36
36
|
module ResourceProviderMixin
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
def self.included(klass)
|
38
|
+
# Warning here be dragons.
|
39
|
+
# Create a new anonymous module, klass will be the module that
|
40
|
+
# actually included ResourceProviderMixin. We want to keep a reference
|
41
|
+
# to that locked down so that we can close over it and use it in the
|
42
|
+
# "real" .included defined below to find the original relative consts.
|
43
|
+
mod = Module.new do
|
44
|
+
# Use define_method instead of def so we can close over klass and mod.
|
45
|
+
define_method(:included) do |inner_klass|
|
46
|
+
# Has to be explicit because super inside define_method.
|
47
|
+
super(inner_klass)
|
48
|
+
# Cargo this .included to things which include us.
|
49
|
+
inner_klass.extend(mod)
|
50
|
+
# Dispatch to submodules, inner_klass is the most recent includer.
|
51
|
+
if inner_klass < Chef::Resource
|
52
|
+
# Use klass::Resource to look up relative to the original module.
|
53
|
+
inner_klass.class_exec { include klass::Resource }
|
54
|
+
elsif inner_klass < Chef::Provider
|
55
|
+
# As above, klass::Provider.
|
56
|
+
inner_klass.class_exec { include klass::Provider }
|
57
|
+
end
|
46
58
|
end
|
47
59
|
end
|
60
|
+
# Add our .included to the original includer.
|
61
|
+
klass.extend(mod)
|
48
62
|
end
|
49
|
-
|
50
|
-
extend ClassMethods
|
51
63
|
end
|
52
64
|
end
|
53
65
|
end
|
data/lib/poise/version.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#
|
16
16
|
|
17
17
|
eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
|
18
|
+
|
18
19
|
gem 'chef', github: 'chef/chef'
|
19
|
-
|
20
|
-
|
20
|
+
gem 'halite', github: 'poise/halite'
|
21
|
+
gem 'poise-boiler', github: 'poise/poise-boiler'
|
@@ -78,5 +78,49 @@ describe Poise::Helpers::OptionCollector do
|
|
78
78
|
it { is_expected.to run_poise_test('test').with(options: {'one' => '1'}, value: 2) }
|
79
79
|
end # /context with a normal attribute too
|
80
80
|
|
81
|
+
context 'with a parser Proc' do
|
82
|
+
resource(:poise_test) do
|
83
|
+
include Poise::Helpers::LWRPPolyfill
|
84
|
+
include described_class
|
85
|
+
attribute(:options, option_collector: true, parser: proc {|val| parse(val) })
|
86
|
+
def parse(val)
|
87
|
+
{name: val}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
recipe do
|
91
|
+
poise_test 'test' do
|
92
|
+
options '1'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it { is_expected.to run_poise_test('test').with(options: {'name' => '1'}) }
|
97
|
+
end # /context with a parser Proc
|
98
|
+
|
99
|
+
context 'with a parser Symbol' do
|
100
|
+
resource(:poise_test) do
|
101
|
+
include Poise::Helpers::LWRPPolyfill
|
102
|
+
include described_class
|
103
|
+
attribute(:options, option_collector: true, parser: :parse)
|
104
|
+
def parse(val)
|
105
|
+
{name: val}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
recipe do
|
109
|
+
poise_test 'test' do
|
110
|
+
options '1'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it { is_expected.to run_poise_test('test').with(options: {'name' => '1'}) }
|
115
|
+
end # /context with a parser Symbol
|
116
|
+
|
117
|
+
context 'with an invalid parse' do
|
118
|
+
it do
|
119
|
+
expect do
|
120
|
+
resource(:poise_test).send(:attribute, :options, option_collector: true, parser: 'invalid')
|
121
|
+
end.to raise_error(Poise::Error)
|
122
|
+
end
|
123
|
+
end # /context with an invalid parser
|
124
|
+
|
81
125
|
# TODO: Write tests for mixed symbol/string data
|
82
126
|
end
|
@@ -116,7 +116,7 @@ describe Poise::Helpers::Subresources::Container do
|
|
116
116
|
it { is_expected.to run_inner('inner') }
|
117
117
|
end # /context with a no namespace
|
118
118
|
|
119
|
-
context 'with a no namespace and
|
119
|
+
context 'with a no namespace and an empty inner name' do
|
120
120
|
resource(:poise_test) do
|
121
121
|
include described_class
|
122
122
|
container_namespace(false)
|
@@ -127,6 +127,21 @@ describe Poise::Helpers::Subresources::Container do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
it { is_expected.to run_poise_test('container') }
|
131
|
+
it { is_expected.to run_inner('container') }
|
132
|
+
end # /context with a no namespace and an empty inner name
|
133
|
+
|
134
|
+
context 'with a no namespace and no inner name' do
|
135
|
+
resource(:poise_test) do
|
136
|
+
include described_class
|
137
|
+
container_namespace(false)
|
138
|
+
end
|
139
|
+
recipe do
|
140
|
+
poise_test 'container' do
|
141
|
+
inner
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
130
145
|
it { is_expected.to run_poise_test('container') }
|
131
146
|
it { is_expected.to run_inner('container') }
|
132
147
|
end # /context with a no namespace and no inner name
|
@@ -37,6 +37,28 @@ module ResourceProviderMixinTest
|
|
37
37
|
class Provider < Chef::Provider
|
38
38
|
include Test
|
39
39
|
end
|
40
|
+
|
41
|
+
module Test2
|
42
|
+
include Poise::Utils::ResourceProviderMixin
|
43
|
+
|
44
|
+
module Resource
|
45
|
+
include Test
|
46
|
+
end
|
47
|
+
|
48
|
+
module Provider
|
49
|
+
include Test
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Resource2 < Chef::Resource
|
54
|
+
include Test
|
55
|
+
include Test2
|
56
|
+
end
|
57
|
+
|
58
|
+
class Provider2 < Chef::Provider
|
59
|
+
include Test
|
60
|
+
include Test2
|
61
|
+
end
|
40
62
|
end
|
41
63
|
|
42
64
|
describe Poise::Utils::ResourceProviderMixin do
|
@@ -49,4 +71,18 @@ describe Poise::Utils::ResourceProviderMixin do
|
|
49
71
|
subject { ResourceProviderMixinTest::Provider }
|
50
72
|
it { is_expected.to be < ResourceProviderMixinTest::Test::Provider }
|
51
73
|
end
|
74
|
+
|
75
|
+
context 'with nested usage' do
|
76
|
+
context 'in a resource' do
|
77
|
+
subject { ResourceProviderMixinTest::Resource2 }
|
78
|
+
it { is_expected.to be < ResourceProviderMixinTest::Test::Resource }
|
79
|
+
it { is_expected.to be < ResourceProviderMixinTest::Test2::Resource }
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'in a provider' do
|
83
|
+
subject { ResourceProviderMixinTest::Provider2 }
|
84
|
+
it { is_expected.to be < ResourceProviderMixinTest::Test::Provider }
|
85
|
+
it { is_expected.to be < ResourceProviderMixinTest::Test2::Provider }
|
86
|
+
end
|
87
|
+
end # /context with nested usage
|
52
88
|
end
|
data/test/spec/utils_spec.rb
CHANGED
@@ -106,5 +106,29 @@ describe Poise::Utils do
|
|
106
106
|
end
|
107
107
|
it { is_expected.to eq 'halite_cookbook_other' }
|
108
108
|
end # /context with a Halite cookbook on a shared prefix
|
109
|
+
|
110
|
+
context 'with a Halite cookbook on a nested prefix' do
|
111
|
+
let(:filename) { '/source/halite_cookbook/vendor/other/lib/something.rb' }
|
112
|
+
before do
|
113
|
+
cookbooks << Chef::CookbookVersion.new('other_cookbook', '/test/other_cookbook').tap do |ver|
|
114
|
+
ver.library_filenames << '/test/other_cookbook/libraries/default.rb'
|
115
|
+
ver.recipe_filenames << '/test/other_cookbook/recipe/default.rb'
|
116
|
+
end
|
117
|
+
cookbooks << Chef::CookbookVersion.new('halite_cookbook', '/test/halite_cookbook').tap do |ver|
|
118
|
+
def ver.halite_root
|
119
|
+
'/source/halite_cookbook'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
cookbooks << Chef::CookbookVersion.new('halite_cookbook_other', '/test/halite_cookbook/vendor/other').tap do |ver|
|
123
|
+
def ver.halite_root
|
124
|
+
'/source/halite_cookbook/vendor/other'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
cookbooks << Chef::CookbookVersion.new('my_cookbook', '/test/my_cookbook').tap do |ver|
|
128
|
+
ver.recipe_filenames << '/test/my_cookbook/recipe/default.rb'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
it { is_expected.to eq 'halite_cookbook_other' }
|
132
|
+
end # /context with a Halite cookbook on a nested prefix
|
109
133
|
end # /describe .find_cookbook_name
|
110
134
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Kantrowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: halite
|