poise-languages 1.0.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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +32 -0
- data/LICENSE +202 -0
- data/README.md +27 -0
- data/Rakefile +17 -0
- data/lib/poise_languages.rb +25 -0
- data/lib/poise_languages/command.rb +25 -0
- data/lib/poise_languages/command/mixin.rb +231 -0
- data/lib/poise_languages/error.rb +21 -0
- data/lib/poise_languages/scl.rb +24 -0
- data/lib/poise_languages/scl/mixin.rb +110 -0
- data/lib/poise_languages/scl/resource.rb +124 -0
- data/lib/poise_languages/system.rb +24 -0
- data/lib/poise_languages/system/mixin.rb +165 -0
- data/lib/poise_languages/system/resource.rb +202 -0
- data/lib/poise_languages/utils.rb +49 -0
- data/lib/poise_languages/utils/which.rb +49 -0
- data/lib/poise_languages/version.rb +20 -0
- data/poise-languages.gemspec +40 -0
- data/test/gemfiles/chef-12.gemfile +19 -0
- data/test/gemfiles/master.gemfile +22 -0
- data/test/spec/command/mixin_spec.rb +328 -0
- data/test/spec/scl/mixin_spec.rb +209 -0
- data/test/spec/scl/resource_spec.rb +51 -0
- data/test/spec/spec_helper.rb +18 -0
- data/test/spec/system/mixin_spec.rb +172 -0
- data/test/spec/system/resource_spec.rb +123 -0
- data/test/spec/utils/which_spec.rb +69 -0
- data/test/spec/utils_spec.rb +55 -0
- metadata +132 -0
@@ -0,0 +1,202 @@
|
|
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 'chef/resource'
|
18
|
+
require 'chef/provider'
|
19
|
+
require 'poise'
|
20
|
+
|
21
|
+
|
22
|
+
module PoiseLanguages
|
23
|
+
module System
|
24
|
+
# A `poise_language_system` resource to manage installing a language from
|
25
|
+
# system packages. This is an internal implementation detail of
|
26
|
+
# poise-languages.
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 1.0
|
30
|
+
# @provides poise_languages_system
|
31
|
+
# @action install
|
32
|
+
# @action upgrade
|
33
|
+
# @action uninstall
|
34
|
+
class Resource < Chef::Resource
|
35
|
+
include Poise
|
36
|
+
provides(:poise_languages_system)
|
37
|
+
actions(:install, :upgrade, :uninstall)
|
38
|
+
|
39
|
+
# @!attribute package_name
|
40
|
+
# Name of the main package for the language.
|
41
|
+
# @return [String]
|
42
|
+
attribute(:package_name, kind_of: String, name_attribute: true)
|
43
|
+
# @!attribute dev_package
|
44
|
+
# Name of the development headers package, or false to disable
|
45
|
+
# installing headers. By default computed from {package_name}.
|
46
|
+
# @return [String, false]
|
47
|
+
attribute(:dev_package, kind_of: [String, FalseClass], default: lazy { default_dev_package })
|
48
|
+
# @!attribute dev_package_overrides
|
49
|
+
# A hash of override names for dev packages that don't match the normal
|
50
|
+
# naming scheme.
|
51
|
+
# @return [Hash<String, String>]
|
52
|
+
attribute(:dev_package_overrides, kind_of: Hash, default: lazy { {} })
|
53
|
+
# @!attribute package_version
|
54
|
+
# Version of the package(s) to install. This is distinct from {version},
|
55
|
+
# and is the specific version package version, not the language version.
|
56
|
+
# By default this is unset meaning the latest version will be used.
|
57
|
+
# @return [String, nil]
|
58
|
+
attribute(:package_version, kind_of: [String, NilClass])
|
59
|
+
# @!attribute parent
|
60
|
+
# Resource for the language runtime. Used only for messages.
|
61
|
+
# @return [Chef::Resource]
|
62
|
+
attribute(:parent, kind_of: Chef::Resource, required: true)
|
63
|
+
# @!attributes version
|
64
|
+
# Language version prefix. This prefix determines which version of the
|
65
|
+
# language to install, following prefix matching rules.
|
66
|
+
# @return [String]
|
67
|
+
attribute(:version, kind_of: String, default: '')
|
68
|
+
|
69
|
+
# Compute the default package name for the development headers.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
def default_dev_package
|
73
|
+
# Check for an override.
|
74
|
+
return dev_package_overrides[package_name] if dev_package_overrides.include?(package_name)
|
75
|
+
suffix = node.value_for_platform_family(debian: '-dev', rhel: '-devel', fedora: '-devel')
|
76
|
+
# Platforms like Arch and Gentoo don't need this anyway. I've got no
|
77
|
+
# clue how Amazon Linux does this.
|
78
|
+
if suffix
|
79
|
+
package_name + suffix
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# The default provider for `poise_languages_system`.
|
87
|
+
#
|
88
|
+
# @api private
|
89
|
+
# @since 1.0
|
90
|
+
# @see Resource
|
91
|
+
# @provides poise_languages_system
|
92
|
+
class Provider < Chef::Provider
|
93
|
+
include Poise
|
94
|
+
provides(:poise_languages_system)
|
95
|
+
|
96
|
+
# The `install` action for the `poise_languages_system` resource.
|
97
|
+
#
|
98
|
+
# @return [void]
|
99
|
+
def action_install
|
100
|
+
run_package_action(:install)
|
101
|
+
end
|
102
|
+
|
103
|
+
# The `upgrade` action for the `poise_languages_system` resource.
|
104
|
+
#
|
105
|
+
# @return [void]
|
106
|
+
def action_upgrade
|
107
|
+
run_package_action(:upgrade)
|
108
|
+
end
|
109
|
+
|
110
|
+
# The `uninstall` action for the `poise_languages_system` resource.
|
111
|
+
#
|
112
|
+
# @return [void]
|
113
|
+
def action_uninstall
|
114
|
+
action = node.platform_family?('debian') ? :purge : :remove
|
115
|
+
package_resources(action).each do |resource|
|
116
|
+
resource.run_action(action)
|
117
|
+
new_resource.updated_by_last_action(true) if resource.updated_by_last_action?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# Create package resource objects for all needed packages. These are created
|
124
|
+
# directly and not added to the resource collection.
|
125
|
+
#
|
126
|
+
# @return [Array<Chef::Resource::Package>]
|
127
|
+
def package_resources(action)
|
128
|
+
packages = {new_resource.package_name => new_resource.package_version}
|
129
|
+
# If we are supposed to install the dev package, grab it using the same
|
130
|
+
# version as the main package.
|
131
|
+
if new_resource.dev_package
|
132
|
+
packages[new_resource.dev_package] = new_resource.package_version
|
133
|
+
end
|
134
|
+
|
135
|
+
Chef::Log.debug("[#{new_resource.parent}] Building package resource using #{packages.inspect}.")
|
136
|
+
@package_resource ||= if node.platform_family?('rhel', 'fedora', 'amazon')
|
137
|
+
# @todo Can't use multi-package mode with yum pending https://github.com/chef/chef/issues/3476.
|
138
|
+
packages.map do |name, version|
|
139
|
+
Chef::Resource::Package.new(name, run_context).tap do |r|
|
140
|
+
r.version(version)
|
141
|
+
r.action(action)
|
142
|
+
r.declared_type = :package
|
143
|
+
end
|
144
|
+
end
|
145
|
+
else
|
146
|
+
[Chef::Resource::Package.new(packages.keys, run_context).tap do |r|
|
147
|
+
r.version(packages.values)
|
148
|
+
r.action(action)
|
149
|
+
r.declared_type = :package
|
150
|
+
end]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Run the requested action for all package resources. This exists because
|
155
|
+
# we inject our version check in to the provider directly and I want to
|
156
|
+
# only run the provider action once for performance. It is otherwise
|
157
|
+
# mostly a stripped down version of Chef::Resource#run_action.
|
158
|
+
#
|
159
|
+
# @param action [Symbol] Action to run on all package resources.
|
160
|
+
# @return [void]
|
161
|
+
def run_package_action(action)
|
162
|
+
package_resources(action).each do |resource|
|
163
|
+
# Reset it so we have a clean baseline.
|
164
|
+
resource.updated_by_last_action(false)
|
165
|
+
# Grab the provider.
|
166
|
+
provider = resource.provider_for_action(action)
|
167
|
+
provider.action = action
|
168
|
+
# Check the candidate version if needed
|
169
|
+
patch_load_current_resource!(provider, new_resource.version)
|
170
|
+
# Run our action.
|
171
|
+
Chef::Log.debug("[#{new_resource.parent}] Running #{provider} with #{action}")
|
172
|
+
provider.run_action(action)
|
173
|
+
# Check updated flag.
|
174
|
+
new_resource.updated_by_last_action(true) if resource.updated_by_last_action?
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Hack a provider object to run our verification code.
|
179
|
+
#
|
180
|
+
# @param provider [Chef::Provider] Provider object to patch.
|
181
|
+
# @param version [String] Language version prefix to check for.
|
182
|
+
# @return [void]
|
183
|
+
def patch_load_current_resource!(provider, version)
|
184
|
+
# Create a closure module and inject it.
|
185
|
+
provider.extend Module.new {
|
186
|
+
# Patch load_current_resource to run our verification logic after
|
187
|
+
# the normal code.
|
188
|
+
define_method(:load_current_resource) do
|
189
|
+
super().tap do |_|
|
190
|
+
each_package do |package_name, new_version, current_version, candidate_version|
|
191
|
+
unless candidate_version.start_with?(version)
|
192
|
+
raise PoiseLanguages::Error.new("Package #{package_name} would install #{candidate_version}, which does not match #{version.empty? ? version.inspect : version}. Please set the package_name or package_version provider options.")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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 'shellwords'
|
18
|
+
|
19
|
+
require 'poise_languages/utils/which'
|
20
|
+
|
21
|
+
|
22
|
+
module PoiseLanguages
|
23
|
+
module Utils
|
24
|
+
include Which
|
25
|
+
extend self
|
26
|
+
|
27
|
+
# Convert the executable in a string or array command to an absolute path.
|
28
|
+
#
|
29
|
+
# @param cmd [String, Array<String>] Command to fix up.
|
30
|
+
# @param path [String, nil] Replacement $PATH for executable lookup.
|
31
|
+
# @return [String, Array<String>]
|
32
|
+
def absolute_command(cmd, path: nil)
|
33
|
+
was_array = cmd.is_a?(Array)
|
34
|
+
cmd = if was_array
|
35
|
+
cmd.dup
|
36
|
+
else
|
37
|
+
Shellwords.split(cmd)
|
38
|
+
end
|
39
|
+
# Don't try to touch anything if the first value looks like a flag.
|
40
|
+
if cmd.first && !cmd.first.start_with?('-')
|
41
|
+
# If which returns false, just leave it I guess.
|
42
|
+
cmd[0] = which(cmd.first, path: path) || cmd.first
|
43
|
+
end
|
44
|
+
cmd = Shellwords.join(cmd) unless was_array
|
45
|
+
cmd
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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
|
+
|
18
|
+
module PoiseLanguages
|
19
|
+
module Utils
|
20
|
+
# Replacement module for Chef::Mixin::Which with a slight improvement.
|
21
|
+
#
|
22
|
+
# @since 1.0.0
|
23
|
+
# @see Which#which
|
24
|
+
module Which
|
25
|
+
extend self
|
26
|
+
|
27
|
+
# A replacement for Chef::Mixin::Which#which that allows using something
|
28
|
+
# other than an environment variable if needed.
|
29
|
+
#
|
30
|
+
# @param cmd [String] Executable to search for.
|
31
|
+
# @param extra_path [Array<String>] Extra directories to always search.
|
32
|
+
# @param path [String, nil] Replacement $PATH value.
|
33
|
+
# @return [String, false]
|
34
|
+
def which(cmd, extra_path: %w{/bin /usr/bin /sbin /usr/sbin}, path: nil)
|
35
|
+
# Allow passing something other than the real env var.
|
36
|
+
path ||= ENV['PATH']
|
37
|
+
# Based on Chef::Mixin::Which#which
|
38
|
+
# Copyright 2010-2015, Chef Softare, Inc.
|
39
|
+
paths = path.split(File::PATH_SEPARATOR) + extra_path
|
40
|
+
paths.each do |candidate_path|
|
41
|
+
filename = ::File.join(candidate_path, cmd)
|
42
|
+
return filename if ::File.executable?(filename)
|
43
|
+
end
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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
|
+
|
18
|
+
module PoiseLanguages
|
19
|
+
VERSION = '1.0.0'
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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
|
+
lib = File.expand_path('../lib', __FILE__)
|
18
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
|
+
require 'poise_languages/version'
|
20
|
+
|
21
|
+
Gem::Specification.new do |spec|
|
22
|
+
spec.name = 'poise-languages'
|
23
|
+
spec.version = PoiseLanguages::VERSION
|
24
|
+
spec.authors = ['Noah Kantrowitz']
|
25
|
+
spec.email = %w{noah@coderanger.net}
|
26
|
+
spec.description = "A Chef cookbook to help writing language cooobkoks."
|
27
|
+
spec.summary = spec.description
|
28
|
+
spec.homepage = 'https://github.com/poise/poise-languages'
|
29
|
+
spec.license = 'Apache 2.0'
|
30
|
+
|
31
|
+
spec.files = `git ls-files`.split($/)
|
32
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
33
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
34
|
+
spec.require_paths = %w{lib}
|
35
|
+
|
36
|
+
spec.add_dependency 'halite', '~> 1.0'
|
37
|
+
spec.add_dependency 'poise', '~> 2.3'
|
38
|
+
|
39
|
+
spec.add_development_dependency 'poise-boiler', '~> 1.0'
|
40
|
+
end
|
@@ -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.0'
|
@@ -0,0 +1,22 @@
|
|
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', github: 'chef/chef'
|
20
|
+
gem 'halite', github: 'poise/halite'
|
21
|
+
gem 'poise', github: 'poise/poise'
|
22
|
+
gem 'poise-boiler', github: 'poise/poise-boiler'
|
@@ -0,0 +1,328 @@
|
|
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
|
+
|
19
|
+
describe PoiseLanguages::Command::Mixin do
|
20
|
+
resource(:mylang_runtime) do
|
21
|
+
include Poise(container: true)
|
22
|
+
attribute(:mylang_binary, default: '/binary')
|
23
|
+
attribute(:mylang_environment, default: {'MYLANG_PATH' => '/thing'})
|
24
|
+
end
|
25
|
+
provider(:mylang_runtime)
|
26
|
+
let(:runtime) { chef_run.mylang_runtime('parent') }
|
27
|
+
|
28
|
+
describe PoiseLanguages::Command::Mixin::Resource do
|
29
|
+
resource(:poise_test) do
|
30
|
+
klass = described_class
|
31
|
+
include Module.new {
|
32
|
+
include klass
|
33
|
+
language_command_mixin(:mylang)
|
34
|
+
}
|
35
|
+
def which(name)
|
36
|
+
"/which/#{name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
provider(:poise_test)
|
40
|
+
|
41
|
+
describe '#parent_$name' do
|
42
|
+
context 'with a parent' do
|
43
|
+
recipe do
|
44
|
+
mylang_runtime 'parent'
|
45
|
+
poise_test 'test'
|
46
|
+
end
|
47
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: chef_run.mylang_runtime('parent')) }
|
48
|
+
end # /context with a parent
|
49
|
+
|
50
|
+
context 'with no parent' do
|
51
|
+
recipe do
|
52
|
+
poise_test 'test'
|
53
|
+
end
|
54
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: nil) }
|
55
|
+
end # /context with no parent
|
56
|
+
|
57
|
+
context 'with two containers' do
|
58
|
+
recipe do
|
59
|
+
mylang_runtime 'parent'
|
60
|
+
poise_test 'test'
|
61
|
+
mylang_runtime 'other'
|
62
|
+
end
|
63
|
+
|
64
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: chef_run.mylang_runtime('parent')) }
|
65
|
+
end # /context with two containers
|
66
|
+
end # /describe #parent_$name
|
67
|
+
|
68
|
+
describe '#timeout' do
|
69
|
+
recipe do
|
70
|
+
poise_test 'test' do
|
71
|
+
# Be explicit because Kernel#timeout is part of the timeout.rb lib.
|
72
|
+
self.timeout(123)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'with timeout enabled' do
|
77
|
+
it { is_expected.to run_poise_test('test').with(timeout: 123) }
|
78
|
+
end # /context with timeout enabled
|
79
|
+
|
80
|
+
context 'with timeout disabled' do
|
81
|
+
resource(:poise_test) do
|
82
|
+
klass = described_class
|
83
|
+
include Module.new {
|
84
|
+
include klass
|
85
|
+
language_command_mixin(:poise, timeout: false)
|
86
|
+
}
|
87
|
+
end
|
88
|
+
it { expect { subject }.to raise_error NoMethodError }
|
89
|
+
end # /context with timeout disabled
|
90
|
+
end # /describe #timeout
|
91
|
+
|
92
|
+
describe '#$name' do
|
93
|
+
context 'with an implicit parent' do
|
94
|
+
recipe do
|
95
|
+
mylang_runtime 'parent'
|
96
|
+
poise_test 'test'
|
97
|
+
end
|
98
|
+
|
99
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/binary') }
|
100
|
+
end # /context with an implicit parent
|
101
|
+
|
102
|
+
context 'with a parent resource' do
|
103
|
+
recipe do
|
104
|
+
r = mylang_runtime 'parent'
|
105
|
+
poise_test 'test' do
|
106
|
+
mylang r
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/binary') }
|
111
|
+
end # /context with a parent resource
|
112
|
+
|
113
|
+
context 'with a parent resource name' do
|
114
|
+
recipe do
|
115
|
+
mylang_runtime 'parent'
|
116
|
+
poise_test 'test' do
|
117
|
+
mylang 'parent'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/binary') }
|
122
|
+
end # /context with a parent resource name
|
123
|
+
|
124
|
+
context 'with a parent resource name that looks like a path' do
|
125
|
+
let(:runtime) { chef_run.mylang_runtime('/usr/bin/other') }
|
126
|
+
recipe do
|
127
|
+
mylang_runtime '/usr/bin/other' do
|
128
|
+
mylang_binary name
|
129
|
+
end
|
130
|
+
poise_test 'test' do
|
131
|
+
mylang '/usr/bin/other'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/usr/bin/other') }
|
136
|
+
end # /context with a parent resource name that looks like a path
|
137
|
+
|
138
|
+
context 'with a path' do
|
139
|
+
recipe do
|
140
|
+
poise_test 'test' do
|
141
|
+
mylang '/usr/bin/other'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: nil, mylang: '/usr/bin/other') }
|
146
|
+
end # /context with a path
|
147
|
+
|
148
|
+
context 'with a path and an implicit parent' do
|
149
|
+
recipe do
|
150
|
+
mylang_runtime 'parent'
|
151
|
+
poise_test 'test' do
|
152
|
+
mylang '/usr/bin/other'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/usr/bin/other') }
|
157
|
+
end # /context with a path and an implicit parent
|
158
|
+
|
159
|
+
context 'with an invalid parent' do
|
160
|
+
recipe do
|
161
|
+
poise_test 'test' do
|
162
|
+
mylang 'test'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it { expect { subject }.to raise_error Chef::Exceptions::ResourceNotFound }
|
167
|
+
end # /context with an invalid parent
|
168
|
+
|
169
|
+
context 'with no parent' do
|
170
|
+
recipe do
|
171
|
+
poise_test 'test'
|
172
|
+
end
|
173
|
+
|
174
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: nil, mylang: '/which/mylang') }
|
175
|
+
end # /context with no parent
|
176
|
+
end # /describe #$name
|
177
|
+
|
178
|
+
describe '#$name_from_parent' do
|
179
|
+
context 'with a resource parent' do
|
180
|
+
recipe do
|
181
|
+
mylang_runtime 'parent'
|
182
|
+
r = poise_test 'first' do
|
183
|
+
mylang 'parent'
|
184
|
+
end
|
185
|
+
mylang_runtime 'other'
|
186
|
+
poise_test 'test' do
|
187
|
+
mylang_from_parent r
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/binary') }
|
192
|
+
end # /context with a resource parent
|
193
|
+
|
194
|
+
context 'with a path parent' do
|
195
|
+
recipe do
|
196
|
+
r = poise_test 'first' do
|
197
|
+
mylang '/other'
|
198
|
+
end
|
199
|
+
poise_test 'test' do
|
200
|
+
mylang_from_parent r
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: nil, mylang: '/other') }
|
205
|
+
end # /context with a path parent
|
206
|
+
end # /describe #$name_from_parent
|
207
|
+
|
208
|
+
context 'as a method' do
|
209
|
+
resource(:poise_test) do
|
210
|
+
include Module.new {
|
211
|
+
include PoiseLanguages::Command::Mixin::Resource(:mylang)
|
212
|
+
}
|
213
|
+
end
|
214
|
+
recipe do
|
215
|
+
mylang_runtime 'parent'
|
216
|
+
poise_test 'test'
|
217
|
+
end
|
218
|
+
|
219
|
+
it { is_expected.to run_poise_test('test').with(parent_mylang: runtime, mylang: '/binary') }
|
220
|
+
end # /context as a method
|
221
|
+
end # /describe PoiseLanguages::Command::Mixin::Resource
|
222
|
+
|
223
|
+
describe PoiseLanguages::Command::Mixin::Provider do
|
224
|
+
resource(:poise_test) do
|
225
|
+
include PoiseLanguages::Command::Mixin::Resource(:mylang)
|
226
|
+
include Poise::Helpers::LWRPPolyfill
|
227
|
+
attribute(:command)
|
228
|
+
attribute(:expect)
|
229
|
+
attribute(:options, default: [])
|
230
|
+
def which(name)
|
231
|
+
"/which/#{name}"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe '#$name_shell_out' do
|
236
|
+
provider(:poise_test) do
|
237
|
+
klass = described_class
|
238
|
+
include Module.new {
|
239
|
+
include klass
|
240
|
+
language_command_mixin(:mylang)
|
241
|
+
}
|
242
|
+
def action_run
|
243
|
+
expect(self).to receive(:shell_out).with(*new_resource.expect)
|
244
|
+
mylang_shell_out(new_resource.command, *new_resource.options)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'with a parent' do
|
249
|
+
recipe do
|
250
|
+
mylang_runtime 'parent'
|
251
|
+
poise_test 'test' do
|
252
|
+
command 'foo'
|
253
|
+
expect ['/binary foo', {environment: {'MYLANG_PATH' => '/thing'}, timeout: 900}]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
it { run_chef }
|
257
|
+
end # /context with a parent
|
258
|
+
|
259
|
+
context 'without a parent' do
|
260
|
+
recipe do
|
261
|
+
poise_test 'test' do
|
262
|
+
command 'foo'
|
263
|
+
expect ['/which/mylang foo', {timeout: 900}]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
it { run_chef }
|
267
|
+
end # /context without a parent
|
268
|
+
|
269
|
+
context 'with a timeout' do
|
270
|
+
recipe do
|
271
|
+
mylang_runtime 'parent'
|
272
|
+
poise_test 'test' do
|
273
|
+
timeout 300
|
274
|
+
command 'foo'
|
275
|
+
expect ['/binary foo', {environment: {'MYLANG_PATH' => '/thing'}, timeout: 300}]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
it { run_chef }
|
279
|
+
end # /context with a timeout
|
280
|
+
|
281
|
+
context 'with environment options' do
|
282
|
+
recipe do
|
283
|
+
mylang_runtime 'parent'
|
284
|
+
poise_test 'test' do
|
285
|
+
command 'foo'
|
286
|
+
options [{environment: {'OTHER' => 'foo'}}]
|
287
|
+
expect ['/binary foo', {environment: {'MYLANG_PATH' => '/thing', 'OTHER' => 'foo'}, timeout: 900}]
|
288
|
+
end
|
289
|
+
end
|
290
|
+
it { run_chef }
|
291
|
+
end # /context with environment options
|
292
|
+
|
293
|
+
context 'with an array command' do
|
294
|
+
recipe do
|
295
|
+
poise_test 'test' do
|
296
|
+
command ['foo']
|
297
|
+
expect [['/which/mylang', 'foo'], {timeout: 900}]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
it { run_chef }
|
301
|
+
end # /context with an array command
|
302
|
+
end # /describe #$name_shell_out
|
303
|
+
|
304
|
+
describe '#$name_shell_out!' do
|
305
|
+
provider(:poise_test) do
|
306
|
+
klass = described_class
|
307
|
+
include Module.new {
|
308
|
+
include klass
|
309
|
+
language_command_mixin(:mylang)
|
310
|
+
}
|
311
|
+
def action_run
|
312
|
+
fake_output = double()
|
313
|
+
expect(fake_output).to receive(:error!)
|
314
|
+
expect(self).to receive(:mylang_shell_out).with(*new_resource.expect).and_return(fake_output)
|
315
|
+
mylang_shell_out!(new_resource.command, *new_resource.options)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
recipe do
|
319
|
+
poise_test 'test' do
|
320
|
+
command 'foo'
|
321
|
+
expect ['foo']
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
it { run_chef }
|
326
|
+
end # /describe #$name_shell_out!
|
327
|
+
end # /describe PoiseLanguages::Command::Mixin::Provider
|
328
|
+
end
|