mirror of
https://github.com/fluent/fluentd-ui.git
synced 2025-08-12 01:07:09 +02:00
194 lines
5.8 KiB
Ruby
194 lines
5.8 KiB
Ruby
require "fileutils"
|
|
require "json"
|
|
require "httpclient"
|
|
|
|
class Plugin
|
|
class GemError < StandardError; end
|
|
|
|
WORKING = []
|
|
|
|
include ActiveModel::Model
|
|
|
|
attr_accessor :gem_name, :version
|
|
validates :gem_name, presence: true
|
|
validates :version, presence: true
|
|
|
|
def to_param
|
|
gem_name
|
|
end
|
|
|
|
def install!
|
|
return if installed?
|
|
|
|
self.version ||= latest_version
|
|
if valid? && gem_install
|
|
File.open(gemfile_path, "a") do |f|
|
|
f.puts format_gemfile
|
|
end
|
|
end
|
|
end
|
|
|
|
def uninstall!
|
|
return unless installed?
|
|
|
|
# NOTE: do not uninstall gem actually for now. because it is not necessary, and slow job
|
|
# NOTE: should uninstall that situation: installed verions is A, self.version is NOT A. only check gem_name.
|
|
if gem_uninstall
|
|
new_gemfile = ""
|
|
File.open(gemfile_path).each_line do |line|
|
|
next if line.include?(%Q|gem "#{gem_name}"|)
|
|
new_gemfile << line
|
|
end
|
|
File.open(gemfile_path, "w"){|f| f.write new_gemfile }
|
|
end
|
|
end
|
|
|
|
def upgrade!(new_version)
|
|
return unless installed?
|
|
|
|
upgrade = self.class.new(gem_name: self.gem_name, version: new_version)
|
|
if self.valid? && upgrade.valid?
|
|
self.uninstall!
|
|
upgrade.install!
|
|
self.version = upgrade.version
|
|
end
|
|
end
|
|
|
|
def installed?
|
|
self.class.installed.find do |plugin|
|
|
plugin.gem_name == gem_name
|
|
end
|
|
end
|
|
|
|
def format_gemfile
|
|
self.version ||= latest_version
|
|
%Q|gem "#{gem_name}", "#{version}"|
|
|
end
|
|
|
|
def installed_version
|
|
return unless inst = installed?
|
|
inst.version
|
|
end
|
|
|
|
def latest_version?
|
|
installed_version == latest_version
|
|
end
|
|
|
|
def latest_version
|
|
@latest_version ||= JSON.parse(gem_versions).map {|ver| Gem::Version.new ver["number"] }.max.to_s
|
|
end
|
|
|
|
def released_versions
|
|
@released_versions ||= JSON.parse(gem_versions).map {|ver| ver["number"]}.sort_by{|ver| Gem::Version.new ver}.reverse
|
|
end
|
|
|
|
def self.gemfile_changed?
|
|
# if true, rails server needs to restart. new installed/removed gems are.
|
|
@initial_gemfile_content != File.read(gemfile_path)
|
|
end
|
|
|
|
def self.installed
|
|
return [] unless File.exist?(gemfile_path)
|
|
File.read(gemfile_path).scan(/"(.*?)", "(.*?)"/).map do |plugin|
|
|
new(gem_name: plugin[0], version: plugin[1])
|
|
end
|
|
end
|
|
|
|
def self.recommended
|
|
# TODO: how to manage recommended plugins?
|
|
[
|
|
Plugin.new(gem_name: "fluent-plugin-mongo"),
|
|
Plugin.new(gem_name: "fluent-plugin-s3"),
|
|
Plugin.new(gem_name: "fluent-plugin-secure-forward"),
|
|
Plugin.new(gem_name: "fluent-plugin-forest"),
|
|
Plugin.new(gem_name: "fluent-plugin-couch"),
|
|
Plugin.new(gem_name: "fluent-plugin-dstat"),
|
|
Plugin.new(gem_name: "fluent-plugin-parser"),
|
|
Plugin.new(gem_name: "fluent-plugin-map"),
|
|
Plugin.new(gem_name: "fluent-plugin-grep"),
|
|
Plugin.new(gem_name: "fluent-plugin-webhdfs"),
|
|
Plugin.new(gem_name: "fluent-plugin-rewrite-tag-filter"),
|
|
Plugin.new(gem_name: "fluent-plugin-td"),
|
|
Plugin.new(gem_name: "fluent-plugin-elasticsearch"),
|
|
Plugin.new(gem_name: "fluent-plugin-datacounter"),
|
|
Plugin.new(gem_name: "fluent-plugin-flowcounter"),
|
|
Plugin.new(gem_name: "fluent-plugin-numeric-counter"),
|
|
Plugin.new(gem_name: "fluent-plugin-record-reformer"),
|
|
Plugin.new(gem_name: "fluent-plugin-pghstore"),
|
|
Plugin.new(gem_name: "fluent-plugin-notifier"),
|
|
Plugin.new(gem_name: "fluent-plugin-mysqlslowquery"),
|
|
Plugin.new(gem_name: "fluent-plugin-boundio"),
|
|
Plugin.new(gem_name: "fluent-plugin-ses"),
|
|
Plugin.new(gem_name: "fluent-plugin-groonga"),
|
|
Plugin.new(gem_name: "fluent-plugin-websocket"),
|
|
Plugin.new(gem_name: "fluent-plugin-pgjson"),
|
|
Plugin.new(gem_name: "fluent-plugin-say"),
|
|
Plugin.new(gem_name: "fluent-plugin-uri_decoder"),
|
|
Plugin.new(gem_name: "fluent-plugin-rds-log"),
|
|
Plugin.new(gem_name: "fluent-plugin-msgpack-rpc"),
|
|
Plugin.new(gem_name: "fluent-plugin-reemit"),
|
|
Plugin.new(gem_name: "fluent-plugin-multiprocess"),
|
|
Plugin.new(gem_name: "fluent-plugin-dbi"),
|
|
Plugin.new(gem_name: "fluent-plugin-serialport"),
|
|
Plugin.new(gem_name: "fluent-plugin-loggly"),
|
|
Plugin.new(gem_name: "fluent-plugin-out-solr"),
|
|
Plugin.new(gem_name: "fluent-plugin-riak"),
|
|
Plugin.new(gem_name: "fluent-plugin-couchbase"),
|
|
Plugin.new(gem_name: "fluent-plugin-unique-counter"),
|
|
Plugin.new(gem_name: "fluent-plugin-flatten-hash"),
|
|
Plugin.new(gem_name: "fluent-plugin-solr"),
|
|
Plugin.new(gem_name: "fluent-plugin-dd"),
|
|
Plugin.new(gem_name: "fluent-plugin-gstore"),
|
|
Plugin.new(gem_name: "fluent-plugin-mongokpi"),
|
|
Plugin.new(gem_name: "fluent-plugin-jsonbucket"),
|
|
]
|
|
end
|
|
|
|
def self.gemfile_path
|
|
Rails.root + "Gemfile.plugins"
|
|
end
|
|
|
|
def self.pristine!
|
|
unless File.exists?(gemfile_path)
|
|
File.open(gemfile_path, "w") do |f|
|
|
f.write "# USED BY fluentd-ui internally\n"
|
|
end
|
|
end
|
|
@initial_gemfile_content = File.read(gemfile_path)
|
|
end
|
|
pristine!
|
|
|
|
def gemfile_path
|
|
self.class.gemfile_path
|
|
end
|
|
|
|
private
|
|
|
|
def gem_versions
|
|
url = "https://rubygems.org/api/v1/versions/#{gem_name}.json"
|
|
Rails.cache.fetch(url, expires_in: 60.minutes) do # NOTE: 60.minutes could be changed if it doesn't fit
|
|
res = HTTPClient.get(url)
|
|
res.body if res.code == 200
|
|
end
|
|
end
|
|
|
|
def gem_install
|
|
fluent_gem("install", gem_name, "-v", version)
|
|
end
|
|
|
|
def gem_uninstall
|
|
fluent_gem("uninstall", gem_name, "-x", "-a")
|
|
end
|
|
|
|
def fluent_gem(*commands)
|
|
# NOTE: use `fluent-gem` instead of `gem`
|
|
Bundler.with_clean_env do
|
|
# NOTE: this app is under the Bundler, so call `system` in with_clean_env is Bundler jail breaking
|
|
unless system(*%W(fluent-gem) + commands) # TODO: should grab stdout/stderr
|
|
raise GemError, "failed command #{commands.join(" ")}"
|
|
end
|
|
end
|
|
true
|
|
end
|
|
end
|