poise 2.4.0 → 2.5.0
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 -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:
|