Skip to content

Commit 0b830bb

Browse files
authored
Merge pull request #920 from tylerjl/plugin-provider-refactor-exists
Refactor `exists` logic for plugin provider
2 parents 813c729 + 8842350 commit 0b830bb

File tree

4 files changed

+63
-91
lines changed

4 files changed

+63
-91
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#### Features
44

55
#### Fixes
6+
* Rewrote the `exists?` logic for the `elasticsearch_plugin` provider. This fundamentally changes how the module detects the presence of plugins but should be backwards compatible.
67

78
## 6.2.0 (February 9, 2018)
89

lib/puppet/provider/elastic_plugin.rb

Lines changed: 47 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -21,66 +21,44 @@ def homedir
2121
end
2222

2323
def exists?
24-
if !File.exists?(pluginfile)
25-
debug "Plugin file #{pluginfile} does not exist"
26-
return false
27-
elsif File.exists?(pluginfile) && readpluginfile != pluginfile_content
28-
debug "Got #{readpluginfile} Expected #{pluginfile_content}. Removing for reinstall"
29-
self.destroy
30-
return false
31-
else
32-
debug "Plugin exists"
33-
return true
34-
end
35-
end
36-
37-
# Returns the content that should be written to the pluginfile.
38-
#
39-
# @return String
40-
def pluginfile_content
41-
return @resource[:name] if is1x?
42-
43-
if @resource[:name].split("/").count == 1 # Official plugin
44-
version = plugin_version(@resource[:name])
45-
return "#{@resource[:name]}/#{version}"
46-
else
47-
return @resource[:name]
48-
end
49-
end
24+
# First, attempt to list whether the named plugin exists by finding a
25+
# plugin descriptor file, which each plugin should have. We must wildcard
26+
# the name to match meta plugins, see upstream issue for this change:
27+
# https://github.com/elastic/elasticsearch/pull/28022
28+
properties = Dir[File.join(@resource[:plugin_dir], plugin_path, '*plugin-descriptor.properties')]
29+
return false if properties.empty?
5030

51-
# Get the path for the `.name` file for the provider helper.
52-
#
53-
# @return String
54-
# path for the pluginfile
55-
def pluginfile
56-
if @resource[:plugin_path]
57-
File.join(
58-
@resource[:plugin_dir],
59-
@resource[:plugin_path],
60-
'.name'
61-
)
62-
else
63-
File.join(
64-
@resource[:plugin_dir],
65-
Puppet_X::Elastic::plugin_name(@resource[:name]),
66-
'.name'
67-
)
31+
begin
32+
# Use the basic name format that the plugin tool supports in order to
33+
# determine the version from the resource name.
34+
plugin_version = Puppet_X::Elastic.plugin_version(@resource[:name])
35+
36+
# Naively parse the Java .properties file to check version equality.
37+
# Because we don't have the luxury of installing arbitrary gems, perform
38+
# simple parse with a degree of safety checking in the call chain
39+
installed_version = IO.readlines(properties.first).map(&:strip).reject do |line|
40+
line.start_with?('#') or line.empty?
41+
end.map do |property|
42+
property.split('=')
43+
end.reject do |pairs|
44+
pairs.length != 2
45+
end.to_h['version']
46+
47+
if installed_version != plugin_version
48+
debug "Elasticsearch plugin #{@resource[:name]} not version #{plugin_version}, reinstalling"
49+
destroy
50+
return false
51+
end
52+
rescue ElasticPluginParseFailure
53+
# If there is no version string, we do not check version equality
54+
debug "No version found in #{@resource[:name]}, not enforcing any version"
6855
end
69-
end
7056

71-
# Write plugfile file `.name` contents to disk.
72-
def writepluginfile
73-
File.open(pluginfile, 'w') do |file|
74-
file.write pluginfile_content
75-
end
57+
true
7658
end
7759

78-
# Get pluginfile contents.
79-
#
80-
# @return String
81-
def readpluginfile
82-
f = File.open(pluginfile)
83-
f.readline
60+
def plugin_path
61+
@resource[:plugin_path] || Puppet_X::Elastic.plugin_name(@resource[:name])
8462
end
8563

8664
# Intelligently returns the correct installation arguments for version 1
@@ -91,20 +69,18 @@ def readpluginfile
9169
def install1x
9270
if !@resource[:url].nil?
9371
[
94-
Puppet_X::Elastic::plugin_name(@resource[:name]),
72+
Puppet_X::Elastic.plugin_name(@resource[:name]),
9573
'--url',
9674
@resource[:url]
9775
]
9876
elsif !@resource[:source].nil?
9977
[
100-
Puppet_X::Elastic::plugin_name(@resource[:name]),
78+
Puppet_X::Elastic.plugin_name(@resource[:name]),
10179
'--url',
10280
"file://#{@resource[:source]}"
10381
]
10482
else
105-
[
106-
@resource[:name]
107-
]
83+
[@resource[:name]]
10884
end
10985
end
11086

@@ -115,17 +91,11 @@ def install1x
11591
# arguments to pass to the plugin installation utility
11692
def install2x
11793
if !@resource[:url].nil?
118-
[
119-
@resource[:url]
120-
]
94+
[@resource[:url]]
12195
elsif !@resource[:source].nil?
122-
[
123-
"file://#{@resource[:source]}"
124-
]
96+
["file://#{@resource[:source]}"]
12597
else
126-
[
127-
@resource[:name]
128-
]
98+
[@resource[:name]]
12999
end
130100
end
131101

@@ -134,14 +104,12 @@ def install2x
134104
#
135105
# @return Array
136106
# of flags for command-line tools
137-
def proxy_args url
107+
def proxy_args(url)
138108
parsed = URI(url)
139-
['http', 'https'].map do |schema|
140-
[:host, :port, :user, :password].map do |param|
109+
%w[http https].map do |schema|
110+
%i[host port user password].map do |param|
141111
option = parsed.send(param)
142-
if not option.nil?
143-
"-D#{schema}.proxy#{param.to_s.capitalize}=#{option}"
144-
end
112+
"-D#{schema}.proxy#{param.to_s.capitalize}=#{option}" unless option.nil?
145113
end
146114
end.flatten.compact
147115
end
@@ -168,14 +136,12 @@ def create
168136
retry if retry_times < retry_count
169137
raise "Failed to install plugin. Received error: #{e.inspect}"
170138
end
171-
172-
writepluginfile
173139
end
174140

175141
# Remove this plugin from the host.
176142
def destroy
177143
with_environment do
178-
plugin(['remove', Puppet_X::Elastic::plugin_name(@resource[:name])])
144+
plugin(['remove', Puppet_X::Elastic.plugin_name(@resource[:name])])
179145
end
180146
end
181147

@@ -191,26 +157,19 @@ def is1x?
191157
end
192158

193159
def is2x?
194-
(Puppet::Util::Package.versioncmp(es_version, '2.0.0') >= 0) && (Puppet::Util::Package.versioncmp(es_version, '3.0.0') < 0)
160+
(Puppet::Util::Package.versioncmp(es_version, '2.0.0') >= 0) && \
161+
(Puppet::Util::Package.versioncmp(es_version, '3.0.0') < 0)
195162
end
196163

197164
def batch_capable?
198165
Puppet::Util::Package.versioncmp(es_version, '2.2.0') >= 0
199166
end
200167

201-
# Determine the plugin version.
202-
def plugin_version(plugin_name)
203-
_vendor, _plugin, version = plugin_name.split('/')
204-
return es_version if is2x? && version.nil?
205-
return version.scan(/\d+\.\d+\.\d+(?:\-\S+)?/).first unless version.nil?
206-
false
207-
end
208-
209168
# Run a command wrapped in necessary env vars
210169
def with_environment(&block)
211170
env_vars = {
212171
'ES_JAVA_OPTS' => @resource[:java_opts],
213-
'ES_PATH_CONF' => @resource[:configdir],
172+
'ES_PATH_CONF' => @resource[:configdir]
214173
}
215174
saved_vars = {}
216175

lib/puppet_x/elastic/plugin_parsing.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
1+
class ElasticPluginParseFailure < StandardError; end
2+
13
module Puppet_X
24
module Elastic
35
def self.plugin_name(raw_name)
46
plugin_split(raw_name, 1)
57
end
68

9+
def self.plugin_version(raw_name)
10+
v = plugin_split(raw_name, 2, false).gsub(/^[^0-9]*/, '')
11+
raise ElasticPluginParseFailure, "could not parse version, got '#{v}'" if v.empty?
12+
v
13+
end
14+
715
# Attempt to guess at the plugin's final directory name
8-
def self.plugin_split(original_string, position)
16+
def self.plugin_split(original_string, position, soft_fail = true)
917
# Try both colon (maven) and slash-delimited (github/elastic.co) names
1018
%w[/ :].each do |delimiter|
1119
parts = original_string.split(delimiter)
1220
# If the string successfully split, assume we found the right format
1321
return parts[position].gsub(/(elasticsearch-|es-)/, '') unless parts[position].nil?
1422
end
1523

16-
# Fallback to the originally passed plugin name
24+
raise(
25+
ElasticPluginParseFailure,
26+
"could not find element '#{position}' in #{original_string}"
27+
) unless soft_fail
28+
1729
original_string
1830
end
1931
end # of Elastic

spec/unit/provider/elasticsearch_plugin/shared_examples.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
let(:resource_name) { 'appbaseio/dejaVu' }
156156

157157
it 'maintains mixed-case names' do
158-
expect(provider.pluginfile).to include('dejaVu')
158+
expect(provider.plugin_path).to include('dejaVu')
159159
end
160160
end
161161

0 commit comments

Comments
 (0)