poise 2.0.0 → 2.0.1
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.
- 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
|