Skip to content

Commit 95eb164

Browse files
committed
Add missing implementation
Signed-off-by: Kentaro Hayashi <[email protected]>
1 parent 2ad0f44 commit 95eb164

File tree

4 files changed

+392
-5
lines changed

4 files changed

+392
-5
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
require 'open-uri'
2+
require 'json'
3+
require 'tmpdir'
4+
5+
module Fluent
6+
module Plugin
7+
module FluentPackage
8+
class UpdateChecker
9+
DEFAULT_PACKAGE_CONFIG_PATH = "/opt/fluent/share/config"
10+
def initialize(options={})
11+
@logger = options[:logger]
12+
@options = options
13+
@newer_versions = []
14+
@newer_lts_versions = []
15+
@major_lts_updates = []
16+
@major_updates = []
17+
@tmp_dir = Dir.mktmpdir("fluent_package_update_notifier")
18+
begin
19+
require ENV["FLUENT_PACKAGE_CONFIG"] || DEFAULT_PACKAGE_CONFIG_PATH
20+
rescue LoadError
21+
@logger.error "Failed to load #{ENV["FLUENT_PACKAGE_CONFIG"] || DEFAULT_PACKAGE_CONFIG_PATH}"
22+
end
23+
end
24+
25+
def tags_cached?
26+
File.exist?(cached_tags_path) and
27+
(Time.now - 60 * 60 * 24) < File.mtime(cached_tags_path)
28+
end
29+
30+
def cached_tags_path
31+
ENV["FLUENT_PACKAGE_TAGS_PATH"] ?
32+
ENV["FLUENT_PACKAGE_TAGS_PATH"] : "#{@tmp_dir}/fluent-package-tags.json"
33+
end
34+
35+
def release_tags_url
36+
"https://api.github.com/repos/fluent/fluent-package-builder/tags"
37+
end
38+
39+
def fetch_tags
40+
begin
41+
if tags_cached?
42+
yield JSON.parse(File.open(cached_tags_path).read)
43+
else
44+
URI.open(release_tags_url) do |resource|
45+
File.open(cached_tags_path, "w+") do |f|
46+
json = resource.read
47+
f.write(json)
48+
yield JSON.parse(json)
49+
end
50+
end
51+
end
52+
rescue => e
53+
@logger.error "Failed to fetch tags", error: e
54+
end
55+
end
56+
57+
def same_lts_series?(base_version, target_version)
58+
# compare [major, 0] pair information
59+
@options[:lts] and [base_version.segments.first, 0] == target_version.segments[..1]
60+
end
61+
62+
def major_lts_update?(base_version, target_version)
63+
@options[:lts] and
64+
base_version.segments.first < target_version.segments.first and
65+
[base_version.segments[1], target_version.segments[1]] == [0, 0]
66+
end
67+
68+
def check_update_versions
69+
current_version = Gem::Version.new("#{PACKAGE_VERSION}")
70+
fetch_tags do |releases|
71+
releases.each do |release|
72+
version = release["name"]
73+
next if version.include?("-") # skip test artifacts
74+
target_version = Gem::Version.new(version.delete("v"))
75+
if target_version > current_version
76+
major = current_version.segments.first
77+
if same_lts_series?(current_version, target_version)
78+
@newer_lts_versions << version
79+
elsif version.start_with?("v#{major}")
80+
@newer_versions << version
81+
else
82+
# major upgrade standard/LTS version
83+
if major_lts_update?(current_version, target_version)
84+
# LTS
85+
@major_lts_updates << version
86+
else
87+
@major_updates << version
88+
end
89+
end
90+
end
91+
end
92+
end
93+
FileUtils.rm_rf(@tmp_dir)
94+
end
95+
96+
def notify_update_log
97+
candidates = nil
98+
if @options[:lts]
99+
if @options[:notify_major_upgrade]
100+
candidates = if @major_lts_updates.count > 0
101+
@major_lts_updates
102+
elsif @newer_lts_versions.count > 0
103+
@newer_lts_versions
104+
end
105+
else
106+
candidates = @newer_lts_versions
107+
end
108+
else
109+
if @options[:notify_major_upgrade]
110+
candidates = if @major_updates.count > 0
111+
@major_updates
112+
elsif @newer_versions.count > 0
113+
@newer_versions
114+
end
115+
else
116+
candidates = @newer_versions
117+
end
118+
end
119+
if candidates
120+
# Assume the version information are already sorted in descendant order by GitHub API
121+
url = "https://github.com/fluent/fluent-package-builder/releases/tag/#{candidates.first}"
122+
message = "fluent-package #{candidates.first} is available! See #{url} in details."
123+
else
124+
message = "No update for fluent-package #{PACKAGE_VERSION}"
125+
end
126+
case @options[:notify_level]
127+
when :warn
128+
@logger.warn(message)
129+
when :info
130+
@logger.info(message)
131+
end
132+
end
133+
134+
def run
135+
check_update_versions
136+
notify_update_log
137+
end
138+
end
139+
end
140+
end
141+
end

lib/fluent/plugin/in_fluent_package_update_notifier.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,63 @@
1414
# limitations under the License.
1515

1616
require "fluent/plugin/input"
17+
require "fluent/log"
18+
require "fluent/config/error"
19+
require_relative "./fluent_package_update_checker"
1720

1821
module Fluent
1922
module Plugin
2023
class FluentPackageUpdateNotifierInput < Fluent::Plugin::Input
2124
Fluent::Plugin.register_input("fluent_package_update_notifier", self)
25+
26+
helpers :timer
27+
28+
desc "Notify fluent-package updates which depends on channel (e.g. Monitor LTS by default)"
29+
config_param :lts, :bool, default: true
30+
31+
desc "Notify whether major upgrade is available or not (e.g. from v5 to v6)"
32+
config_param :notify_major_upgrade, :bool, default: true
33+
34+
desc "Specify notification log level when update is available"
35+
config_param :notify_level, :enum, list: [:info, :warn], default: :info
36+
37+
desc "Notify checking update intervals"
38+
config_param :notify_interval, :integer, default: 60 * 60 * 24
39+
40+
def configure(conf)
41+
super
42+
end
43+
44+
def start
45+
super
46+
check_fluent_pacakge_update_information
47+
timer_execute(:in_fluent_package_update_notifier_worker, @notify_interval, &method(:run))
48+
end
49+
50+
def shutdown
51+
super
52+
end
53+
54+
def run
55+
check_fluent_pacakge_update_information
56+
end
57+
58+
private
59+
60+
def check_fluent_pacakge_update_information
61+
begin
62+
options = {
63+
lts: @lts,
64+
notify_major_upgrade: @notify_major_upgrade,
65+
notify_level: @notify_level,
66+
logger: log
67+
}
68+
checker = Fluent::Plugin::FluentPackage::UpdateChecker.new(options)
69+
checker.run
70+
rescue => e
71+
log.error "Failed to check updates: #{e.message}"
72+
end
73+
end
2274
end
2375
end
2476
end

test/helper.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
require "fluent/test"
33
require "fluent/test/driver/input"
44
require "fluent/test/helpers"
5+
require 'fluent/config/element'
6+
require 'fluent/system_config'
7+
require 'fluent/engine'
58

69
Test::Unit::TestCase.include(Fluent::Test::Helpers)
710
Test::Unit::TestCase.extend(Fluent::Test::Helpers)

0 commit comments

Comments
 (0)