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.
@@ -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