poise-languages 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,21 @@
|
|
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
|
+
class Error < ::Exception
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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 Scl
|
20
|
+
autoload :Mixin, 'poise_languages/scl/mixin'
|
21
|
+
autoload :Resource, 'poise_languages/scl/resource'
|
22
|
+
autoload :Provider, 'poise_languages/scl/resource'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,110 @@
|
|
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 'poise_languages/scl/resource'
|
18
|
+
|
19
|
+
|
20
|
+
module PoiseLanguages
|
21
|
+
module Scl
|
22
|
+
module Mixin
|
23
|
+
private
|
24
|
+
|
25
|
+
def install_scl_package
|
26
|
+
pkg = scl_package
|
27
|
+
poise_languages_scl pkg[:name] do
|
28
|
+
parent new_resource
|
29
|
+
url pkg[:url]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def uninstall_scl_package
|
34
|
+
install_scl_package.tap do |r|
|
35
|
+
r.action(:uninstall)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def scl_package
|
40
|
+
@scl_package ||= self.class.find_scl_package(node, options['version']).tap do |p|
|
41
|
+
raise PoiseLanguages::Error.new("No SCL repoistory package for #{node['platform']} #{node['platform_version']}") unless p
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def scl_folder
|
46
|
+
::File.join('', 'opt', 'rh', scl_package[:name])
|
47
|
+
end
|
48
|
+
|
49
|
+
def scl_environment
|
50
|
+
parse_enable_file(::File.join(scl_folder, 'enable'))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Parse an SCL enable file to extract the environment variables set in it.
|
54
|
+
#
|
55
|
+
# @param path [String] Path to the enable file.
|
56
|
+
# @return [Hash<String, String>]
|
57
|
+
def parse_enable_file(path)
|
58
|
+
# Doesn't exist yet, so running Python will fail anyway. Just make sure
|
59
|
+
# it fails in the expected way.
|
60
|
+
return {} unless File.exist?(path)
|
61
|
+
# Yes, this is a bash parser in regex. Feel free to be mad at me.
|
62
|
+
IO.readlines(path).inject({}) do |memo, line|
|
63
|
+
if match = line.match(/^export (\w+)=(.*)$/)
|
64
|
+
memo[match[1]] = match[2].gsub(/\$\{(\w+)(:\+:\$\{\w+\})?\}/) do
|
65
|
+
if $2
|
66
|
+
ENV[$1] ? ":#{ENV[$1]}" : ''
|
67
|
+
else
|
68
|
+
ENV[$1].to_s
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
memo
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module ClassMethods
|
77
|
+
def provides_auto?(node, resource)
|
78
|
+
version = inversion_options(node, resource)['version']
|
79
|
+
!!find_scl_package(node, version)
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_scl_package(node, version)
|
83
|
+
pkg = scl_packages.find {|p| p[:version].start_with?(version) }
|
84
|
+
return unless pkg
|
85
|
+
pkg[:url] = node.value_for_platform(pkg[:urls])
|
86
|
+
return unless pkg[:url]
|
87
|
+
pkg
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def scl_packages
|
93
|
+
@scl_packages ||= []
|
94
|
+
end
|
95
|
+
|
96
|
+
def scl_package(version, name, urls)
|
97
|
+
scl_packages << {version: version, name: name, urls: urls}
|
98
|
+
end
|
99
|
+
|
100
|
+
def included(klass)
|
101
|
+
super
|
102
|
+
klass.extend(ClassMethods)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
extend ClassMethods
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,124 @@
|
|
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 Scl
|
24
|
+
# A `poise_language_scl` resource to manage installing a language from
|
25
|
+
# SCL packages. This is an internal implementation detail of
|
26
|
+
# poise-languages.
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 1.0
|
30
|
+
# @provides poise_languages_scl
|
31
|
+
# @action install
|
32
|
+
# @action uninstall
|
33
|
+
class Resource < Chef::Resource
|
34
|
+
include Poise
|
35
|
+
provides(:poise_languages_scl)
|
36
|
+
actions(:install, :uninstall)
|
37
|
+
|
38
|
+
# @!attribute package_name
|
39
|
+
# Name of the SCL package for the language.
|
40
|
+
# @return [String]
|
41
|
+
attribute(:package_name, kind_of: String, name_attribute: true)
|
42
|
+
# @!attribute url
|
43
|
+
# URL to the SCL repository package for the language.
|
44
|
+
# @return [String]
|
45
|
+
attribute(:url, kind_of: String, required: true)
|
46
|
+
# @!attribute parent
|
47
|
+
# Resource for the language runtime. Used only for messages.
|
48
|
+
# @return [Chef::Resource]
|
49
|
+
attribute(:parent, kind_of: Chef::Resource, required: true)
|
50
|
+
end
|
51
|
+
|
52
|
+
# The default provider for `poise_languages_scl`.
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
# @since 1.0
|
56
|
+
# @see Resource
|
57
|
+
# @provides poise_languages_scl
|
58
|
+
class Provider < Chef::Provider
|
59
|
+
include Poise
|
60
|
+
provides(:poise_languages_scl)
|
61
|
+
|
62
|
+
# The `install` action for the `poise_languages_scl` resource.
|
63
|
+
#
|
64
|
+
# @return [void]
|
65
|
+
def action_install
|
66
|
+
notifying_block do
|
67
|
+
install_scl_utils
|
68
|
+
install_scl_repo_package
|
69
|
+
install_scl_package
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# The `uninstall` action for the `poise_languages_scl` resource.
|
74
|
+
#
|
75
|
+
# @return [void]
|
76
|
+
def action_uninstall
|
77
|
+
notifying_block do
|
78
|
+
uninstall_scl_utils
|
79
|
+
uninstall_scl_repo_package
|
80
|
+
uninstall_scl_package
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def install_scl_utils
|
87
|
+
package 'scl-utils' do
|
88
|
+
action :upgrade # This shouldn't be a problem. Famous last words.
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def install_scl_repo_package
|
93
|
+
rpm_package 'rhscl-' + new_resource.package_name do
|
94
|
+
source new_resource.url
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def install_scl_package
|
99
|
+
yum_package new_resource.package_name do
|
100
|
+
flush_cache before: true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def uninstall_scl_utils
|
105
|
+
install_scl_utils.tap do |r|
|
106
|
+
r.action(:remove)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def uninstall_scl_repo_package
|
111
|
+
install_scl_repo_package.tap do |r|
|
112
|
+
r.action(:remove)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def uninstall_scl_package
|
117
|
+
install_scl_package.tap do |r|
|
118
|
+
r.action(:remove)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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 System
|
20
|
+
autoload :Mixin, 'poise_languages/system/mixin'
|
21
|
+
autoload :Resource, 'poise_languages/system/resource'
|
22
|
+
autoload :Provider, 'poise_languages/system/resource'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,165 @@
|
|
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 'poise_languages/system/resource'
|
18
|
+
|
19
|
+
|
20
|
+
module PoiseLanguages
|
21
|
+
module System
|
22
|
+
module Mixin
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Install a language using system packages.
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
# @return [PoiseLanguages::System::Resource]
|
30
|
+
def install_system_packages
|
31
|
+
dev_package_overrides = system_dev_package_overrides
|
32
|
+
poise_languages_system options['package_name'] || system_package_name do
|
33
|
+
# Otherwise use the default install action.
|
34
|
+
action(:upgrade) if options['package_upgrade']
|
35
|
+
parent new_resource
|
36
|
+
# Don't pass true because we want the default computed behavior for that.
|
37
|
+
dev_package options['dev_package'] unless options['dev_package'] == true
|
38
|
+
dev_package_overrides dev_package_overrides
|
39
|
+
package_version options['package_version'] if options['package_version']
|
40
|
+
version options['version']
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Uninstall a language using system packages.
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
# @return [PoiseLanguages::System::Resource]
|
48
|
+
def uninstall_system_packages
|
49
|
+
install_system_packages.tap do |r|
|
50
|
+
r.action(:uninstall)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Compute all possible package names for a given language version. Must be
|
55
|
+
# implemented by mixin users. Versions are expressed as prefixes so ''
|
56
|
+
# matches all versions, '2' matches 2.x.
|
57
|
+
#
|
58
|
+
# @abstract
|
59
|
+
# @api public
|
60
|
+
# @param version [String] Language version prefix.
|
61
|
+
# @return [Array<String>]
|
62
|
+
def system_package_candidates(version)
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
# Compute the default package name for the base package for this language.
|
67
|
+
#
|
68
|
+
# @api public
|
69
|
+
# @return [String]
|
70
|
+
def system_package_name
|
71
|
+
# Look up all packages for this language on this platform.
|
72
|
+
system_packages = node.value_for_platform(self.class.packages)
|
73
|
+
if !system_packages && self.class.default_package
|
74
|
+
Chef::Log.debug("[#{new_resource}] No known packages for #{node['platform']} #{node['platform_version']}, defaulting to '#{self.class.default_package}'.")
|
75
|
+
system_packages = Array(self.class.default_package)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Find the first value on system_package_candidates that is in system_packages.
|
79
|
+
system_package_candidates(options['version'].to_s).each do |name|
|
80
|
+
return name if system_packages.include?(name)
|
81
|
+
end
|
82
|
+
# No valid candidate. Sad trombone.
|
83
|
+
raise PoiseLanguages::Error.new("Unable to find a candidate package for version #{options['version'].to_s.inspect}. Please set package_name provider option for #{new_resource}.")
|
84
|
+
end
|
85
|
+
|
86
|
+
# A hash mapping package names to their override dev package name.
|
87
|
+
#
|
88
|
+
# @api public
|
89
|
+
# @return [Hash<String, String>]
|
90
|
+
def system_dev_package_overrides
|
91
|
+
{}
|
92
|
+
end
|
93
|
+
|
94
|
+
module ClassMethods
|
95
|
+
# Install this as a default provider for platforms we are relatively
|
96
|
+
# certain work.
|
97
|
+
#
|
98
|
+
# @api private
|
99
|
+
def provides_auto?(node, resource)
|
100
|
+
super || node.platform_family?('debian', 'rhel', 'amazon', 'fedora')
|
101
|
+
end
|
102
|
+
|
103
|
+
# Set some default inversion provider options. Package name can't get
|
104
|
+
# a default value here because that would complicate the handling of
|
105
|
+
# {system_package_candidates}.
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
def default_inversion_options(node, resource)
|
109
|
+
super.merge({
|
110
|
+
# Install dev headers?
|
111
|
+
dev_package: true,
|
112
|
+
# Manual overrides for package name and/or version.
|
113
|
+
package_name: nil,
|
114
|
+
package_version: nil,
|
115
|
+
# Set to true to use action :upgrade on system packages.
|
116
|
+
package_upgrade: false,
|
117
|
+
})
|
118
|
+
end
|
119
|
+
|
120
|
+
# @overload packages()
|
121
|
+
# Return a hash formatted for value_for_platform returning an Array
|
122
|
+
# of package names.
|
123
|
+
# @return [Hash]
|
124
|
+
# @overload packages(default_package, packages)
|
125
|
+
# Define what system packages are available for this language on each
|
126
|
+
# platform.
|
127
|
+
# @param default_package [String] Default package name for platforms
|
128
|
+
# not otherwise defined.
|
129
|
+
# @param [Hash] Hash formatted for value_for_platform returning an
|
130
|
+
# Array of package names.
|
131
|
+
# @return [Hash]
|
132
|
+
def packages(default_package=nil, packages=nil)
|
133
|
+
self.default_package(default_package) if default_package
|
134
|
+
if packages
|
135
|
+
@packages = packages
|
136
|
+
end
|
137
|
+
@packages
|
138
|
+
end
|
139
|
+
|
140
|
+
# @overload default_package()
|
141
|
+
# Return the default package name for platforms not otherwise defined.
|
142
|
+
# @return [String]
|
143
|
+
# @overload default_package(name)
|
144
|
+
# Set the default package name for platforms not defined in {packages}.
|
145
|
+
# @param name [String] Package name.
|
146
|
+
# @return [String]
|
147
|
+
def default_package(name=nil)
|
148
|
+
if name
|
149
|
+
@default_package = name
|
150
|
+
end
|
151
|
+
@default_package
|
152
|
+
end
|
153
|
+
|
154
|
+
# @api private
|
155
|
+
def included(klass)
|
156
|
+
super
|
157
|
+
klass.extend(ClassMethods)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
extend ClassMethods
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|