poise 2.4.0 → 2.5.0
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 -0
- data/CHANGELOG.md +13 -0
- data/README.md +9 -0
- data/lib/poise.rb +34 -0
- data/lib/poise/helpers/chefspec_matchers.rb +2 -2
- data/lib/poise/helpers/defined_in.rb +2 -2
- data/lib/poise/helpers/inversion.rb +16 -3
- data/lib/poise/helpers/subcontext_block.rb +1 -1
- data/lib/poise/helpers/subresources/container.rb +2 -1
- data/lib/poise/helpers/template_content.rb +4 -1
- data/lib/poise/provider.rb +2 -0
- data/lib/poise/resource.rb +2 -0
- data/lib/poise/utils.rb +5 -4
- data/lib/poise/utils/shell_out.rb +85 -0
- data/lib/poise/version.rb +1 -1
- data/test/gemfiles/chef-12.0.gemfile +1 -1
- data/test/gemfiles/chef-12.1.gemfile +1 -1
- data/test/gemfiles/chef-12.2.gemfile +1 -1
- data/test/gemfiles/chef-12.4.gemfile +19 -0
- data/test/gemfiles/chef-12.5.gemfile +19 -0
- data/test/spec/helpers/inversion_spec.rb +12 -0
- data/test/spec/helpers/template_content_spec.rb +38 -3
- data/test/spec/poise_spec.rb +133 -0
- data/test/spec/utils/shell_out_spec.rb +104 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59e1a4b84effd92c53b370ae6e5ad4330ac48672
|
4
|
+
data.tar.gz: 8ed9df5c50afd344e838bf637c875cae8c1765f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f924807105ed9ba4b41616df467768d4a5fc2f0259c8f83d8b6fba5b64d744e4cff6fa38ff66e1ab781f94dd6ed3c4f196aadae0733727cbe384569fc367a7b
|
7
|
+
data.tar.gz: ad8775e6a9e0c924e7633f390ca82f7982a4eddb32ca058e3b0e0e988da4766fd074c40022977899012571bacee33c882146f27bff3ae940483cb0f6057c8515
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v2.5.0
|
4
|
+
|
5
|
+
* New property for inversion resources: `provider_no_auto`. Set one or more
|
6
|
+
provider names that will be ignored for automatic resolution for that instance.
|
7
|
+
* Support `variables` as an alias for `options` in template content properties
|
8
|
+
to match the `template` resource.
|
9
|
+
* Template content properties are no longer validated after creation for
|
10
|
+
non-default actions.
|
11
|
+
* Formalize the extra-verbose logging mode for Poise and expose it via helpers.
|
12
|
+
* Extra-verbose logging mode can now be enabled by creating a `/poise_debug` file.
|
13
|
+
* New helper: `poise_shell_out`. Like normal `shell_out` but sets group and
|
14
|
+
environment variables automatically to better defaults.
|
15
|
+
|
3
16
|
## v2.4.0
|
4
17
|
|
5
18
|
* Added return value to `Container#register_subresource` to track if the resource
|
data/README.md
CHANGED
@@ -193,6 +193,15 @@ end
|
|
193
193
|
|
194
194
|
This will be converted to `{key1: 'value1', key2: 'value2'}`. You can also pass a Hash to an option collector attribute just as you would with a normal attribute.
|
195
195
|
|
196
|
+
## Debugging Poise
|
197
|
+
|
198
|
+
Poise has its own extra-verbose level of debug logging that can be enabled in
|
199
|
+
three different ways. You can either set the environment variable `$POISE_DEBUG`,
|
200
|
+
set a node attribute `node['POISE_DEBUG']`, or touch the file `/POISE_DEBUG`.
|
201
|
+
You will see a log message `Extra verbose logging enabled` at the start of the
|
202
|
+
run to confirm Poise debugging has been enabled. Make sure you also set Chef's
|
203
|
+
log level to `debug`, usually via `-l debug` on the command line.
|
204
|
+
|
196
205
|
## Upgrading from Poise 1.x
|
197
206
|
|
198
207
|
The biggest change when upgrading from Poise 1.0 is that the mixin is no longer
|
data/lib/poise.rb
CHANGED
@@ -30,6 +30,36 @@ module Poise
|
|
30
30
|
autoload :Subcontext, 'poise/subcontext'
|
31
31
|
autoload :Utils, 'poise/utils'
|
32
32
|
autoload :VERSION, 'poise/version'
|
33
|
+
|
34
|
+
# Check if Poise's extra debugging output is enabled. This produces a *lot*
|
35
|
+
# of logging.
|
36
|
+
#
|
37
|
+
# @param node [Chef::Node, Chef::RunContext] Optional node to check for
|
38
|
+
# attributes. If not given, Chef.node is used instead.
|
39
|
+
# @return [Boolean]
|
40
|
+
def self.debug?(node=nil)
|
41
|
+
node = node.node if node.is_a?(Chef::RunContext)
|
42
|
+
node ||= Chef.node if defined?(Chef.node)
|
43
|
+
@debug_file_upper = ::File.exist?('/POISE_DEBUG') unless defined?(@debug_file_upper)
|
44
|
+
@debug_file_lower = ::File.exist?('/poise_debug') unless defined?(@debug_file_lower)
|
45
|
+
!!(
|
46
|
+
(ENV['POISE_DEBUG'] && ENV['POISE_DEBUG'] != 'false') ||
|
47
|
+
(ENV['poise_debug'] && ENV['poise_debug'] != 'false') ||
|
48
|
+
(node && node['POISE_DEBUG']) ||
|
49
|
+
(node && node['poise_debug']) ||
|
50
|
+
@debug_file_upper ||
|
51
|
+
@debug_file_lower
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Log a message only if Poise's extra debugging output is enabled.
|
56
|
+
#
|
57
|
+
# @see #debug?
|
58
|
+
# @param msg [String] Log message.
|
59
|
+
# @return [void]
|
60
|
+
def self.debug(msg)
|
61
|
+
Chef::Log.debug(msg) if debug?
|
62
|
+
end
|
33
63
|
end
|
34
64
|
|
35
65
|
# Callable form to allow passing in options:
|
@@ -71,3 +101,7 @@ def Poise(options={})
|
|
71
101
|
|
72
102
|
mod
|
73
103
|
end
|
104
|
+
|
105
|
+
# Display a message if poise_debug is enabled. Off in ChefSpec so I don't get
|
106
|
+
# extra logging stuff that I don't care about.
|
107
|
+
Poise.debug('[Poise] Extra verbose logging enabled') unless defined?(ChefSpec)
|
@@ -61,12 +61,12 @@ module Poise
|
|
61
61
|
#
|
62
62
|
# @see Resource::ResourceName.provides
|
63
63
|
def provides(name, *args, &block)
|
64
|
+
super(name, *args, &block)
|
64
65
|
ChefSpec.define_matcher(name) if defined?(ChefSpec)
|
65
66
|
# Call #actions here to grab any actions from a parent class.
|
66
67
|
actions.each do |action|
|
67
68
|
ChefspecMatchers.create_matcher(name, action)
|
68
69
|
end
|
69
|
-
super(name, *args, &block)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Create matchers for all declared actions.
|
@@ -76,7 +76,7 @@ module Poise
|
|
76
76
|
super.tap do |actions|
|
77
77
|
actions.each do |action|
|
78
78
|
ChefspecMatchers.create_matcher(resource_name, action)
|
79
|
-
end if resource_name
|
79
|
+
end if resource_name && resource_name != :resource && !names.empty?
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -65,9 +65,9 @@ module Poise
|
|
65
65
|
# @return [String]
|
66
66
|
def poise_defined_in_cookbook(run_context, file=nil)
|
67
67
|
file ||= poise_defined_in
|
68
|
-
|
68
|
+
Poise.debug("[#{self.name}] Checking cookbook name for #{file}")
|
69
69
|
Poise::Utils.find_cookbook_name(run_context, file).tap do |cookbook|
|
70
|
-
|
70
|
+
Poise.debug("[#{self.name}] found cookbook #{cookbook.inspect}")
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -83,12 +83,23 @@ module Poise
|
|
83
83
|
resource_names.concat(self.class.subclass_resource_equivalents) if self.class.respond_to?(:subclass_resource_equivalents)
|
84
84
|
# Silly ruby tricks to find the first provider that exists and no more.
|
85
85
|
provider_class = resource_names.lazy.map {|name| Poise::Helpers::Inversion.provider_for(name, node, val) }.select {|x| x }.first
|
86
|
-
|
86
|
+
Poise.debug("[#{self}] Checking for an inversion provider for #{val}: #{provider_class && provider_class.name}")
|
87
87
|
val = provider_class if provider_class
|
88
88
|
end
|
89
89
|
super
|
90
90
|
end
|
91
91
|
|
92
|
+
# Set or return the array of provider names to be blocked from
|
93
|
+
# auto-resolution.
|
94
|
+
#
|
95
|
+
# @param val [String, Array<String>] Value to set.
|
96
|
+
# @return [Array<String>]
|
97
|
+
def provider_no_auto(val=nil)
|
98
|
+
# Coerce to an array.
|
99
|
+
val = Array(val).map(&:to_s) if val
|
100
|
+
set_or_return(:provider_no_auto, val, kind_of: Array, default: [])
|
101
|
+
end
|
102
|
+
|
92
103
|
# @!classmethods
|
93
104
|
module ClassMethods
|
94
105
|
# Options resource class.
|
@@ -290,6 +301,8 @@ module Poise
|
|
290
301
|
opts.update(run_state['*']) if run_state['*']
|
291
302
|
# Options resource options for this provider.
|
292
303
|
opts.update(run_state[provides]) if run_state[provides]
|
304
|
+
# Vomitdebug output for tracking down weirdness.
|
305
|
+
Poise.debug("[#{resource}] Resolved inversion options: #{opts.inspect}")
|
293
306
|
end
|
294
307
|
end
|
295
308
|
|
@@ -352,8 +365,8 @@ module Poise
|
|
352
365
|
end
|
353
366
|
return false unless resource_name_equivalents[inversion_resource]
|
354
367
|
provider_name = resolve_inversion_provider(node, resource)
|
355
|
-
|
356
|
-
provider_name == provides.to_s || ( provider_name == 'auto' && provides_auto?(node, resource) )
|
368
|
+
Poise.debug("[#{resource}] Checking provides? on #{self.name}. Got provider_name #{provider_name.inspect}")
|
369
|
+
provider_name == provides.to_s || ( provider_name == 'auto' && !resource.provider_no_auto.include?(provides.to_s) && provides_auto?(node, resource) )
|
357
370
|
end
|
358
371
|
|
359
372
|
# Subclass hook to provide auto-detection for providers.
|
@@ -35,7 +35,7 @@ module Poise
|
|
35
35
|
if defined?(sub_run_context.initialize_child_state)
|
36
36
|
sub_run_context.initialize_child_state
|
37
37
|
else
|
38
|
-
# Audits was added in 12.1 I
|
38
|
+
# Audits was added in 12.1 I think.
|
39
39
|
sub_run_context.audits = {} if defined?(sub_run_context.audits)
|
40
40
|
# Dup and clear to preserve the default behavior without copy-pasta.
|
41
41
|
sub_run_context.immediate_notification_collection = parent_context.immediate_notification_collection.dup.clear
|
@@ -63,7 +63,8 @@ module Poise
|
|
63
63
|
# we need to jump through some hoops to get it swapped into place.
|
64
64
|
self_ = self
|
65
65
|
order_fixer = Chef::Resource::RubyBlock.new('subresource_order_fixer', @run_context)
|
66
|
-
|
66
|
+
# respond_to? is for <= 12.0.2, remove some day when I stop caring.
|
67
|
+
order_fixer.declared_type = 'ruby_block' if order_fixer.respond_to?(:declared_type=)
|
67
68
|
order_fixer.block do
|
68
69
|
Chef::Log.debug("[#{self_}] Running order fixer")
|
69
70
|
collection = self_.run_context.resource_collection
|
@@ -68,6 +68,9 @@ module Poise
|
|
68
68
|
# Template variables if using a template
|
69
69
|
attribute("#{name_prefix}options", option_collector: true)
|
70
70
|
|
71
|
+
# Make an alias for #variables to match the template resource.
|
72
|
+
alias_method("#{name_prefix}variables", "#{name_prefix}options")
|
73
|
+
|
71
74
|
# The big one, get/set content, but if you are getting and no
|
72
75
|
# explicit content was given, try to render the template
|
73
76
|
define_method("#{name_prefix}content") do |arg=nil, no_compute=false|
|
@@ -97,7 +100,7 @@ module Poise
|
|
97
100
|
old_after_created = instance_method(:after_created)
|
98
101
|
define_method(:after_created) do
|
99
102
|
old_after_created.bind(self).call
|
100
|
-
send("_#{name_prefix}validate")
|
103
|
+
send("_#{name_prefix}validate") if Array(action) == Array(self.class.default_action)
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
data/lib/poise/provider.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#
|
16
16
|
|
17
17
|
require 'poise/helpers'
|
18
|
+
require 'poise/utils'
|
18
19
|
|
19
20
|
|
20
21
|
module Poise
|
@@ -35,6 +36,7 @@ module Poise
|
|
35
36
|
include Poise::Helpers::IncludeRecipe
|
36
37
|
include Poise::Helpers::LWRPPolyfill
|
37
38
|
include Poise::Helpers::NotifyingBlock
|
39
|
+
include Poise::Utils::ShellOut
|
38
40
|
|
39
41
|
# @!classmethods
|
40
42
|
module ClassMethods
|
data/lib/poise/resource.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
#
|
16
16
|
|
17
17
|
require 'poise/helpers'
|
18
|
+
require 'poise/utils'
|
18
19
|
|
19
20
|
|
20
21
|
module Poise
|
@@ -41,6 +42,7 @@ module Poise
|
|
41
42
|
include Poise::Helpers::ResourceName
|
42
43
|
include Poise::Helpers::ResourceSubclass
|
43
44
|
include Poise::Helpers::TemplateContent
|
45
|
+
include Poise::Utils::ShellOut
|
44
46
|
|
45
47
|
# @!classmethods
|
46
48
|
module ClassMethods
|
data/lib/poise/utils.rb
CHANGED
@@ -20,6 +20,7 @@ require 'poise/error'
|
|
20
20
|
module Poise
|
21
21
|
module Utils
|
22
22
|
autoload :ResourceProviderMixin, 'poise/utils/resource_provider_mixin'
|
23
|
+
autoload :ShellOut, 'poise/utils/shell_out'
|
23
24
|
|
24
25
|
extend self
|
25
26
|
|
@@ -37,14 +38,14 @@ module Poise
|
|
37
38
|
# end
|
38
39
|
def find_cookbook_name(run_context, filename)
|
39
40
|
possibles = {}
|
40
|
-
|
41
|
+
Poise.debug("[Poise] Checking cookbook for #{filename.inspect}")
|
41
42
|
run_context.cookbook_collection.each do |name, ver|
|
42
43
|
# This special method is added by Halite::Gem#as_cookbook_version.
|
43
44
|
if ver.respond_to?(:halite_root)
|
44
45
|
# The join is there because ../poise-ruby/lib starts with ../poise so
|
45
46
|
# we want a trailing /.
|
46
47
|
if filename.start_with?(File.join(ver.halite_root, ''))
|
47
|
-
|
48
|
+
Poise.debug("[Poise] Found matching halite_root in #{name}: #{ver.halite_root.inspect}")
|
48
49
|
possibles[ver.halite_root] = name
|
49
50
|
end
|
50
51
|
else
|
@@ -52,9 +53,9 @@ module Poise
|
|
52
53
|
ver.segment_filenames(seg).each do |file|
|
53
54
|
# Put this behind an environment variable because it is verbose
|
54
55
|
# even for normal debugging-level output.
|
55
|
-
|
56
|
+
Poise.debug("[Poise] Checking #{seg} in #{name}: #{file.inspect}")
|
56
57
|
if file == filename
|
57
|
-
|
58
|
+
Poise.debug("[Poise] Found matching #{seg} in #{name}: #{file.inspect}")
|
58
59
|
possibles[file] = name
|
59
60
|
end
|
60
61
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'etc'
|
18
|
+
|
19
|
+
require 'chef/mixin/shell_out'
|
20
|
+
|
21
|
+
|
22
|
+
module Poise
|
23
|
+
module Utils
|
24
|
+
# A mixin to provider a better shell_out.
|
25
|
+
#
|
26
|
+
# @since 2.5.0
|
27
|
+
# @example
|
28
|
+
# Poise::Utils::ShellOut.poise_shell_out('ruby myapp.rb', user: 'myuser')
|
29
|
+
module ShellOut
|
30
|
+
extend self
|
31
|
+
include Chef::Mixin::ShellOut
|
32
|
+
|
33
|
+
# An enhanced version of Chef's `shell_out` which sets some default
|
34
|
+
# parameters. If possible it will set $HOME, $USER, $LOGNAME, and the
|
35
|
+
# group to run as.
|
36
|
+
#
|
37
|
+
# @param command_args [Array] Command arguments to be passed to `shell_out`.
|
38
|
+
# @param options [Hash<Symbol, Object>] Options to be passed to `shell_out`,
|
39
|
+
# with modifications.
|
40
|
+
# @return [Mixlib::ShellOut]
|
41
|
+
def poise_shell_out(*command_args, **options)
|
42
|
+
# Allow the env option shorthand.
|
43
|
+
options[:environment] ||= {}
|
44
|
+
if options[:env]
|
45
|
+
options[:environment].update(options[:env])
|
46
|
+
options.delete(:env)
|
47
|
+
end
|
48
|
+
# Convert environment keys to strings to be safe.
|
49
|
+
options[:environment] = options[:environment].inject({}) do |memo, (key, value)|
|
50
|
+
memo[key.to_s] = value.to_s
|
51
|
+
memo
|
52
|
+
end
|
53
|
+
# Populate some standard environment variables.
|
54
|
+
ent = begin
|
55
|
+
if options[:user].is_a?(Integer)
|
56
|
+
Etc.getpwuid(options[:user])
|
57
|
+
elsif options[:user]
|
58
|
+
Etc.getpwnam(options[:user])
|
59
|
+
end
|
60
|
+
rescue ArgumentError
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
username = ent ? ent.name : options[:name]
|
64
|
+
if username
|
65
|
+
options[:environment]['HOME'] ||= Dir.home(username)
|
66
|
+
options[:environment]['USER'] ||= username
|
67
|
+
# On the off chance they set one manually but not the other.
|
68
|
+
options[:environment]['LOGNAME'] ||= options[:environment]['USER']
|
69
|
+
end
|
70
|
+
# Set the default group on Unix.
|
71
|
+
options[:group] ||= ent.gid if ent
|
72
|
+
# Call Chef's shell_out wrapper.
|
73
|
+
shell_out(*command_args, **options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# The `error!` version of {#poise_shell_out}.
|
77
|
+
#
|
78
|
+
# @see #poise_shell_out
|
79
|
+
# @return [Mixlib::ShellOut]
|
80
|
+
def poise_shell_out!(*command_args)
|
81
|
+
poise_shell_out(*command_args).tap(&:error!)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/poise/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
|
18
|
+
|
19
|
+
gem 'chef', '~> 12.4.3'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
|
18
|
+
|
19
|
+
gem 'chef', '~> 12.5.1'
|
@@ -279,6 +279,7 @@ describe Poise::Helpers::Inversion do
|
|
279
279
|
resource(:poise_test_inversion, step_into: false) do
|
280
280
|
include Poise
|
281
281
|
provides(:poise_test_inversion)
|
282
|
+
attribute(:provider_no_auto, default: [])
|
282
283
|
end
|
283
284
|
provider(:poise_test_inversion) do
|
284
285
|
include described_class
|
@@ -341,6 +342,17 @@ describe Poise::Helpers::Inversion do
|
|
341
342
|
its(:enabled_handlers) { is_expected.to eq [provider(:poise_test_inversion), provider(:poise_test_inversion_other)] }
|
342
343
|
its(:resolve) { is_expected.to eq provider(:poise_test_inversion) }
|
343
344
|
end # /context with a subclassed resource using subclass_providers!
|
345
|
+
|
346
|
+
context 'with provider_no_auto' do
|
347
|
+
recipe(subject: false) do
|
348
|
+
poise_test_inversion 'test' do
|
349
|
+
provider_no_auto %w{inverted}
|
350
|
+
end
|
351
|
+
end
|
352
|
+
let(:test_resource) { chef_run.poise_test_inversion('test') }
|
353
|
+
|
354
|
+
its(:resolve) { is_expected.to eq provider(:poise_test_inversion_other) }
|
355
|
+
end # /context with provider_no_auto
|
344
356
|
end # /describe provider resolution
|
345
357
|
end # /describe Poise::Helpers::Inversion::Provider
|
346
358
|
end
|
@@ -68,7 +68,7 @@ describe Poise::Helpers::TemplateContent do
|
|
68
68
|
end
|
69
69
|
end # /context with a template
|
70
70
|
|
71
|
-
context 'with some template
|
71
|
+
context 'with some template options' do
|
72
72
|
recipe do
|
73
73
|
poise_test 'test' do
|
74
74
|
source 'test.erb'
|
@@ -81,6 +81,21 @@ describe Poise::Helpers::TemplateContent do
|
|
81
81
|
let(:required_template_options) { {'one' => '1', 'two' => 2} }
|
82
82
|
|
83
83
|
it { is_expected.to run_poise_test('test').with(source: 'test.erb', options: required_template_options, content: 'rendered template') }
|
84
|
+
end # /context with some template options
|
85
|
+
|
86
|
+
context 'with some template variables' do
|
87
|
+
recipe do
|
88
|
+
poise_test 'test' do
|
89
|
+
source 'test.erb'
|
90
|
+
variables do
|
91
|
+
one '1'
|
92
|
+
two 2
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
let(:required_template_options) { {'one' => '1', 'two' => 2} }
|
97
|
+
|
98
|
+
it { is_expected.to run_poise_test('test').with(source: 'test.erb', variables: required_template_options, content: 'rendered template') }
|
84
99
|
end # /context with some template variables
|
85
100
|
|
86
101
|
context 'with explicit content' do
|
@@ -131,7 +146,7 @@ describe Poise::Helpers::TemplateContent do
|
|
131
146
|
attribute(:config, template: true, required: true)
|
132
147
|
end
|
133
148
|
|
134
|
-
it { expect{chef_run}.to raise_error
|
149
|
+
it { expect{chef_run}.to raise_error Chef::Exceptions::ValidationFailed }
|
135
150
|
end # /context with required content
|
136
151
|
|
137
152
|
context 'with both source and content' do
|
@@ -142,6 +157,26 @@ describe Poise::Helpers::TemplateContent do
|
|
142
157
|
end
|
143
158
|
end
|
144
159
|
|
145
|
-
it { expect{chef_run}.to raise_error
|
160
|
+
it { expect{chef_run}.to raise_error Chef::Exceptions::ValidationFailed }
|
146
161
|
end # /context with both source and content
|
162
|
+
|
163
|
+
context 'with required content and a non-default action' do
|
164
|
+
resource(:poise_test) do
|
165
|
+
include Poise
|
166
|
+
attribute(:config, template: true, required: true)
|
167
|
+
actions(:one, :two)
|
168
|
+
end
|
169
|
+
provider(:poise_test) do
|
170
|
+
def action_one; end
|
171
|
+
def action_two; end
|
172
|
+
end
|
173
|
+
recipe do
|
174
|
+
poise_test 'test' do
|
175
|
+
action :two
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
it { run_chef }
|
180
|
+
it { expect { chef_run.poise_test('test').config_content }.to raise_error Chef::Exceptions::ValidationFailed }
|
181
|
+
end # /context with required content and a non-default action
|
147
182
|
end
|
data/test/spec/poise_spec.rb
CHANGED
@@ -182,4 +182,137 @@ describe Poise do
|
|
182
182
|
it 'has a fake name when used a function' do
|
183
183
|
expect(Poise().name).to eq 'Poise'
|
184
184
|
end # /it has a fake name when used a function
|
185
|
+
|
186
|
+
describe '.debug?' do
|
187
|
+
let(:debug_files) { [] }
|
188
|
+
before do
|
189
|
+
allow(File).to receive(:exist?).and_call_original
|
190
|
+
expect(File).to receive(:exist?).with(/\/poise_debug/i).twice {|path| debug_files.include?(path) }
|
191
|
+
end
|
192
|
+
around do |ex|
|
193
|
+
# Reset the stat checks both before and after.
|
194
|
+
begin
|
195
|
+
Poise.remove_instance_variable(:@debug_file_upper) if Poise.instance_variable_defined?(:@debug_file_upper)
|
196
|
+
Poise.remove_instance_variable(:@debug_file_lower) if Poise.instance_variable_defined?(:@debug_file_lower)
|
197
|
+
ex.run
|
198
|
+
ensure
|
199
|
+
Poise.remove_instance_variable(:@debug_file_upper) if Poise.instance_variable_defined?(:@debug_file_upper)
|
200
|
+
Poise.remove_instance_variable(:@debug_file_lower) if Poise.instance_variable_defined?(:@debug_file_lower)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
subject { described_class.debug?(chef_runner.node) }
|
204
|
+
|
205
|
+
context 'with no flags' do
|
206
|
+
it { is_expected.to be false }
|
207
|
+
end # /context with no flags
|
208
|
+
|
209
|
+
context 'with $POISE_DEBUG' do
|
210
|
+
around do |ex|
|
211
|
+
begin
|
212
|
+
old = ENV['POISE_DEBUG']
|
213
|
+
ENV['POISE_DEBUG'] = '1'
|
214
|
+
ex.run
|
215
|
+
ensure
|
216
|
+
ENV['POISE_DEBUG'] = old
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it { is_expected.to be true }
|
221
|
+
end # /context with $POISE_DEBUG
|
222
|
+
|
223
|
+
context 'with $POISE_DEBUG = false' do
|
224
|
+
around do |ex|
|
225
|
+
begin
|
226
|
+
old = ENV['POISE_DEBUG']
|
227
|
+
ENV['POISE_DEBUG'] = 'false'
|
228
|
+
ex.run
|
229
|
+
ensure
|
230
|
+
ENV['POISE_DEBUG'] = old
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
it { is_expected.to be false }
|
235
|
+
end # /context with $POISE_DEBUG = false
|
236
|
+
|
237
|
+
context 'with $poise_debug' do
|
238
|
+
around do |ex|
|
239
|
+
begin
|
240
|
+
old = ENV['poise_debug']
|
241
|
+
ENV['poise_debug'] = '1'
|
242
|
+
ex.run
|
243
|
+
ensure
|
244
|
+
ENV['poise_debug'] = old
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
it { is_expected.to be true }
|
249
|
+
end # /context with $poise_debug
|
250
|
+
|
251
|
+
context 'with $poise_debug = false' do
|
252
|
+
around do |ex|
|
253
|
+
begin
|
254
|
+
old = ENV['poise_debug']
|
255
|
+
ENV['poise_debug'] = 'false'
|
256
|
+
ex.run
|
257
|
+
ensure
|
258
|
+
ENV['poise_debug'] = old
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
it { is_expected.to be false }
|
263
|
+
end # /context with $poise_debug = false
|
264
|
+
|
265
|
+
context 'with node["POISE_DEBUG"]' do
|
266
|
+
before { default_attributes['POISE_DEBUG'] = true }
|
267
|
+
it { is_expected.to be true }
|
268
|
+
end # /context with node["POISE_DEBUG"]
|
269
|
+
|
270
|
+
context 'with node["poise_debug"]' do
|
271
|
+
before { default_attributes['poise_debug'] = true }
|
272
|
+
it { is_expected.to be true }
|
273
|
+
end # /context with node["poise_debug"]
|
274
|
+
|
275
|
+
context 'with /POISE_DEBUG' do
|
276
|
+
let(:debug_files) { %w{/POISE_DEBUG} }
|
277
|
+
it { is_expected.to be true }
|
278
|
+
end # /context with /POISE_DEBUG
|
279
|
+
|
280
|
+
context 'with /poise_debug' do
|
281
|
+
let(:debug_files) { %w{/poise_debug} }
|
282
|
+
it { is_expected.to be true }
|
283
|
+
end # /context with /poise_debug
|
284
|
+
|
285
|
+
context 'with a global node' do
|
286
|
+
before do
|
287
|
+
default_attributes['POISE_DEBUG'] = true
|
288
|
+
allow(Chef).to receive(:node).and_return(chef_runner.node)
|
289
|
+
end
|
290
|
+
subject { described_class.debug? }
|
291
|
+
it { is_expected.to be true }
|
292
|
+
end # /context with a global node
|
293
|
+
|
294
|
+
context 'with a run_context' do
|
295
|
+
before { default_attributes['poise_debug'] = true }
|
296
|
+
subject { described_class.debug?(chef_run.run_context) }
|
297
|
+
it { is_expected.to be true }
|
298
|
+
end # /context with a run_context
|
299
|
+
end # /describe .debug?
|
300
|
+
|
301
|
+
describe '.debug' do
|
302
|
+
context 'with debugging disabled' do
|
303
|
+
before { allow(described_class).to receive(:debug?).and_return(false) }
|
304
|
+
it do
|
305
|
+
expect(Chef::Log).to_not receive(:debug)
|
306
|
+
Poise.debug('msg')
|
307
|
+
end
|
308
|
+
end # /context with debugging disabled
|
309
|
+
|
310
|
+
context 'with debugging enabled' do
|
311
|
+
before { allow(described_class).to receive(:debug?).and_return(true) }
|
312
|
+
it do
|
313
|
+
expect(Chef::Log).to receive(:debug).with('msg')
|
314
|
+
Poise.debug('msg')
|
315
|
+
end
|
316
|
+
end # /context with debugging enabled
|
317
|
+
end # /describe .debug
|
185
318
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'spec_helper'
|
18
|
+
require 'etc'
|
19
|
+
|
20
|
+
describe Poise::Utils::ShellOut do
|
21
|
+
let(:arg) { double('command argument') }
|
22
|
+
let(:cmd) { double('Mixlib::ShellOut') }
|
23
|
+
|
24
|
+
describe '.poise_shell_out' do
|
25
|
+
let(:user_ent) { double('Passwd', name: 'testuser', uid: 500, gid: 501) }
|
26
|
+
let(:command_args) { [arg] }
|
27
|
+
let(:expect_args) { [arg, {environment: {}}] }
|
28
|
+
before do
|
29
|
+
allow(Etc).to receive(:getpwuid).with(500).and_return(user_ent)
|
30
|
+
allow(Etc).to receive(:getpwnam).with('testuser').and_return(user_ent)
|
31
|
+
allow(Dir).to receive(:home).with('testuser').and_return('/home/testuser')
|
32
|
+
expect(described_class).to receive(:shell_out).with(*expect_args).and_return(cmd)
|
33
|
+
end
|
34
|
+
subject { described_class.poise_shell_out(*command_args) }
|
35
|
+
|
36
|
+
context 'with no user' do
|
37
|
+
it { is_expected.to be cmd }
|
38
|
+
end # /context with no user
|
39
|
+
|
40
|
+
context 'with a user' do
|
41
|
+
let(:command_args) { [arg, {user: 'testuser'}] }
|
42
|
+
let(:expect_args) { [arg, {user: 'testuser', group: 501, environment: {'HOME' => '/home/testuser', 'USER' => 'testuser', 'LOGNAME' => 'testuser'}}] }
|
43
|
+
it { is_expected.to be cmd }
|
44
|
+
end # /context with a user
|
45
|
+
|
46
|
+
context 'with a uid' do
|
47
|
+
let(:command_args) { [arg, {user: 500}] }
|
48
|
+
let(:expect_args) { [arg, {user: 500, group: 501, environment: {'HOME' => '/home/testuser', 'USER' => 'testuser', 'LOGNAME' => 'testuser'}}] }
|
49
|
+
it { is_expected.to be cmd }
|
50
|
+
end # /context with a uid
|
51
|
+
|
52
|
+
context 'with a group' do
|
53
|
+
let(:command_args) { [arg, {user: 'testuser', group: 'othergroup'}] }
|
54
|
+
let(:expect_args) { [arg, {user: 'testuser', group: 'othergroup', environment: {'HOME' => '/home/testuser', 'USER' => 'testuser', 'LOGNAME' => 'testuser'}}] }
|
55
|
+
it { is_expected.to be cmd }
|
56
|
+
end # /context with a group
|
57
|
+
|
58
|
+
context 'with a $HOME' do
|
59
|
+
let(:command_args) { [arg, {user: 'testuser', environment: {'HOME' => '/other'}}] }
|
60
|
+
let(:expect_args) { [arg, {user: 'testuser', group: 501, environment: {'HOME' => '/other', 'USER' => 'testuser', 'LOGNAME' => 'testuser'}}] }
|
61
|
+
it { is_expected.to be cmd }
|
62
|
+
end # /context with a $HOME
|
63
|
+
|
64
|
+
context 'with a $USER' do
|
65
|
+
let(:command_args) { [arg, {user: 'testuser', environment: {'USER' => 'other'}}] }
|
66
|
+
let(:expect_args) { [arg, {user: 'testuser', group: 501, environment: {'HOME' => '/home/testuser', 'USER' => 'other', 'LOGNAME' => 'other'}}] }
|
67
|
+
it { is_expected.to be cmd }
|
68
|
+
end # /context with a $USER
|
69
|
+
|
70
|
+
context 'with a bad user' do
|
71
|
+
let(:command_args) { [arg, {user: 'testuser'}] }
|
72
|
+
let(:expect_args) { [arg, {user: 'testuser', environment: {}}] }
|
73
|
+
before do
|
74
|
+
allow(Etc).to receive(:getpwnam).with('testuser').and_raise(ArgumentError)
|
75
|
+
end
|
76
|
+
it { is_expected.to be cmd }
|
77
|
+
end # /context with a bad user
|
78
|
+
|
79
|
+
context 'with an env option' do
|
80
|
+
let(:command_args) { [arg, {user: 'testuser', env: {FOO: 'BAR'}}] }
|
81
|
+
let(:expect_args) { [arg, {user: 'testuser', group: 501, environment: {'HOME' => '/home/testuser', 'USER' => 'testuser', 'LOGNAME' => 'testuser', 'FOO' => 'BAR'}}] }
|
82
|
+
it { is_expected.to be cmd }
|
83
|
+
end # /context with an env option
|
84
|
+
|
85
|
+
context 'on Windows' do
|
86
|
+
let(:command_args) { [arg, {user: 'testuser'}] }
|
87
|
+
let(:expect_args) { [arg, {user: 'testuser', environment: {}}] }
|
88
|
+
before do
|
89
|
+
allow(Etc).to receive(:getpwnam).with('testuser').and_return(nil)
|
90
|
+
end
|
91
|
+
it { is_expected.to be cmd }
|
92
|
+
end # /context on Windows
|
93
|
+
end # /describe .poise_shell_out
|
94
|
+
|
95
|
+
describe '.poise_shell_out!' do
|
96
|
+
subject { described_class.poise_shell_out!(arg) }
|
97
|
+
|
98
|
+
it do
|
99
|
+
expect(described_class).to receive(:poise_shell_out).with(arg).and_return(cmd)
|
100
|
+
expect(cmd).to receive(:error!)
|
101
|
+
is_expected.to be cmd
|
102
|
+
end
|
103
|
+
end # /describe .poise_shell_out!
|
104
|
+
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.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Kantrowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: halite
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/poise/subcontext/runner.rb
|
90
90
|
- lib/poise/utils.rb
|
91
91
|
- lib/poise/utils/resource_provider_mixin.rb
|
92
|
+
- lib/poise/utils/shell_out.rb
|
92
93
|
- lib/poise/version.rb
|
93
94
|
- poise.gemspec
|
94
95
|
- test/cookbooks/poise_test/attributes/default.rb
|
@@ -104,6 +105,8 @@ files:
|
|
104
105
|
- test/gemfiles/chef-12.1.gemfile
|
105
106
|
- test/gemfiles/chef-12.2.gemfile
|
106
107
|
- test/gemfiles/chef-12.3.gemfile
|
108
|
+
- test/gemfiles/chef-12.4.gemfile
|
109
|
+
- test/gemfiles/chef-12.5.gemfile
|
107
110
|
- test/gemfiles/chef-12.gemfile
|
108
111
|
- test/gemfiles/master.gemfile
|
109
112
|
- test/integration/default/serverspec/default_spec.rb
|
@@ -132,6 +135,7 @@ files:
|
|
132
135
|
- test/spec/spec_helper.rb
|
133
136
|
- test/spec/subcontext/resource_collection_spec.rb
|
134
137
|
- test/spec/utils/resource_provider_mixin_spec.rb
|
138
|
+
- test/spec/utils/shell_out_spec.rb
|
135
139
|
- test/spec/utils_spec.rb
|
136
140
|
homepage: https://github.com/poise/poise
|
137
141
|
licenses:
|
@@ -171,6 +175,8 @@ test_files:
|
|
171
175
|
- test/gemfiles/chef-12.1.gemfile
|
172
176
|
- test/gemfiles/chef-12.2.gemfile
|
173
177
|
- test/gemfiles/chef-12.3.gemfile
|
178
|
+
- test/gemfiles/chef-12.4.gemfile
|
179
|
+
- test/gemfiles/chef-12.5.gemfile
|
174
180
|
- test/gemfiles/chef-12.gemfile
|
175
181
|
- test/gemfiles/master.gemfile
|
176
182
|
- test/integration/default/serverspec/default_spec.rb
|
@@ -199,5 +205,6 @@ test_files:
|
|
199
205
|
- test/spec/spec_helper.rb
|
200
206
|
- test/spec/subcontext/resource_collection_spec.rb
|
201
207
|
- test/spec/utils/resource_provider_mixin_spec.rb
|
208
|
+
- test/spec/utils/shell_out_spec.rb
|
202
209
|
- test/spec/utils_spec.rb
|
203
210
|
has_rdoc:
|