diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index ecf823b..23fa7b9 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base
helper_method :fluentd_exists?
before_action :login_required
before_action :set_locale
+ before_action :notice_new_fluentd_ui_available
def current_user
return unless session[:succeed_password]
@@ -50,6 +51,12 @@ class ApplicationController < ActionController::Base
private
+ def notice_new_fluentd_ui_available
+ if FluentdUI.update_available?
+ flash[:info] = I18n.t("messages.available_new_fluentd_ui", version: FluentdUI.latest_version, update_url: misc_information_path)
+ end
+ end
+
def find_fluentd
@fluentd = Fluentd.instance
end
diff --git a/app/controllers/misc_controller.rb b/app/controllers/misc_controller.rb
index b405a5e..6a71c33 100644
--- a/app/controllers/misc_controller.rb
+++ b/app/controllers/misc_controller.rb
@@ -9,4 +9,24 @@ class MiscController < ApplicationController
@env = ENV
@plugins = Plugin.installed
end
+
+ def update_fluentd_ui
+ FluentdUiRestart.new.async.perform
+ @current_pid = $$
+ render "update_fluentd_ui", layout: "sign_in"
+ end
+
+ def upgrading_status
+ if FluentdUiRestart::LOCK.present?
+ return render text: "updating"
+ end
+
+ if $$.to_s == params[:old_pid]
+ # restarting fluentd-ui is finished, but PID doesn't changed.
+ # maybe error occured at FluentdUiRestart#perform
+ render text: "failed"
+ else
+ render text: "finished"
+ end
+ end
end
diff --git a/app/models/plugin.rb b/app/models/plugin.rb
index 0d257ad..9da967c 100644
--- a/app/models/plugin.rb
+++ b/app/models/plugin.rb
@@ -22,6 +22,8 @@ class Plugin
self.version ||= latest_version
if valid? && gem_install
+ # NOTE: also updating fluentd-ui gem is used this method, that shouldn't be recorded
+ return true unless gem_name.start_with?("fluent-plugin-")
File.open(gemfile_path, "a") do |f|
f.puts format_gemfile
end
diff --git a/app/views/layouts/sign_in.html.erb b/app/views/layouts/sign_in.html.erb
index cb304a3..23e537d 100644
--- a/app/views/layouts/sign_in.html.erb
+++ b/app/views/layouts/sign_in.html.erb
@@ -18,14 +18,7 @@
-
-
-
<%= t('messages.please_sign_in') %>
-
-
- <%= yield %>
-
-
+ <%= yield %>
diff --git a/app/views/misc/information.html.haml b/app/views/misc/information.html.haml
index cee12d7..2f07f1a 100644
--- a/app/views/misc/information.html.haml
+++ b/app/views/misc/information.html.haml
@@ -1,55 +1,64 @@
- page_title t('.page_title')
-%div.col-lg-6
- %div.panel.panel-info
- %div.panel-heading
- %h4= t ".version"
- %div.panel-body
- %dl{class: "dl-horizontal"}
- %dt ruby
- %dd= RUBY_DESCRIPTION
- %dt fluentd
- %dd= Fluent::VERSION
- %dt fluentd-ui
- %dd= FluentdUI::VERSION
+- if FluentdUI.update_available?
+ .row
+ .col-lg-12
+ %p
+ = link_to misc_update_fluentd_ui_path, class: "btn btn-primary btn-lg", method: :post do
+ = t('.update_fluentd_ui', version: FluentdUI.latest_version)
+ = t('.update_fluentd_ui_caution')
+.row
+ %div.col-lg-6
+ %div.panel.panel-default
+ %div.panel-heading
+ %h4= t ".version"
+ %div.panel-body
+ %dl{class: "dl-horizontal"}
+ %dt ruby
+ %dd= RUBY_DESCRIPTION
+ %dt fluentd
+ %dd= Fluent::VERSION
+ %dt fluentd-ui
+ %dd= FluentdUI::VERSION
-%div.col-lg-6
- %div.panel.panel-default
- %div.panel-heading
- %h4= t('.installed_plugins')
- %div.panel-body
- - if @plugins.present?
- %table{class: "table table-hover", id: "plugins-table"}
- %thead
- %tr
- %th= t('plugins.common.name')
- %th= t('plugins.common.version')
- %tbody
- - @plugins.each do |plugin|
+ %div.col-lg-6
+ %div.panel.panel-default
+ %div.panel-heading
+ %h4= t('.installed_plugins')
+ %div.panel-body
+ - if @plugins.present?
+ %table{class: "table table-hover", id: "plugins-table"}
+ %thead
%tr
- %td= plugin.gem_name
- %td= plugin.installed_version
- - else
- = t "plugins.common.no_installed"
+ %th= t('plugins.common.name')
+ %th= t('plugins.common.version')
+ %tbody
+ - @plugins.each do |plugin|
+ %tr
+ %td= plugin.gem_name
+ %td= plugin.installed_version
+ - else
+ = t "plugins.common.no_installed"
-%div.col-lg-12
- %div.panel.panel-default
- %div.panel-heading
- %h4
- %a{"data-toggle" => "collapse", "href" => "#env-table"}
- = icon('fa-caret-down')
- = t('.env')
- %table{class: "table table-hover collapse", id: "env-table"}
- %thead
- %tr
- %th= t('.env_key')
- %th= t('.env_value')
- %tbody
- - @env.each_pair do |key, value|
+.row
+ %div.col-lg-12
+ %div.panel.panel-default
+ %div.panel-heading
+ %h4
+ %a{"data-toggle" => "collapse", "href" => "#env-table"}
+ = icon('fa-caret-down')
+ = t('.env')
+ %table{class: "table table-hover collapse", id: "env-table"}
+ %thead
%tr
- %td= key
- %td= value
+ %th= t('.env_key')
+ %th= t('.env_value')
+ %tbody
+ - @env.each_pair do |key, value|
+ %tr
+ %td= key
+ %td= value
:javascript
$(document).ready(function() {
diff --git a/app/views/misc/update_fluentd_ui.html.haml b/app/views/misc/update_fluentd_ui.html.haml
new file mode 100644
index 0000000..4d345bb
--- /dev/null
+++ b/app/views/misc/update_fluentd_ui.html.haml
@@ -0,0 +1,45 @@
+.panel.panel-default
+ .panel-heading
+ = t('.update_title')
+ .panel-body
+ #processing
+ = icon('fa-lg fa-gear fa-spin')
+ = t('.updating')
+ #finished{style: "display: none"}
+ = icon('fa-lg fa-check')
+ = t('.update_finish')
+ %p= link_to t('misc.information.page_title'), misc_information_path
+ #failed{style: "display: none"}
+ = icon('fa-lg fa-exclamation-circle')
+ = t('.failed')
+ %p= link_to t('misc.information.page_title'), misc_information_path
+
+:javascript
+ var CURRENT_PID = "#{@current_pid}";
+
+ function ping() {
+ setTimeout(function(){
+ jQuery.ajax({
+ url: "#{misc_upgrading_status_path}",
+ type: "GET",
+ data: { old_pid: CURRENT_PID }
+ })
+ .fail(ping)
+ .done(function(status){
+ switch(status) {
+ case "updating":
+ ping();
+ break;
+ case "failed":
+ jQuery('#processing').hide();
+ jQuery('#failed').show();
+ break;
+ case "finished":
+ jQuery('#processing').hide();
+ jQuery('#finished').show();
+ break;
+ }
+ });
+ }, 3000);
+ }
+ ping();
diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml
index bae46db..5fbf579 100644
--- a/app/views/sessions/new.html.haml
+++ b/app/views/sessions/new.html.haml
@@ -1,8 +1,13 @@
-= render partial: "shared/error"
-= form_for(:session, url: sessions_path) do |f|
- %div.form-group
- = f.text_field :name, placeholder: "Name"
- %div.form-group
- = f.password_field :password, placeholder: "Password"
-
- = submit_tag t("terms.sign_in"), class: "btn btn-success"
+.login-panel.panel.panel-default
+ .panel-heading
+ %h3.panel-title
+ = t('messages.please_sign_in')
+ .panel-body
+ = render partial: "shared/error"
+ = form_for(:session, url: sessions_path) do |f|
+ %div.form-group
+ = f.text_field :name, placeholder: "Name"
+ %div.form-group
+ = f.password_field :password, placeholder: "Password"
+
+ = submit_tag t("terms.sign_in"), class: "btn btn-success"
diff --git a/app/views/shared/_flash.html.haml b/app/views/shared/_flash.html.haml
index c430717..3da9db9 100644
--- a/app/views/shared/_flash.html.haml
+++ b/app/views/shared/_flash.html.haml
@@ -5,4 +5,6 @@
- if flash[:success]
%p.alert.alert-success
=raw flash[:success]
-
+ - if flash[:info]
+ %p.alert.alert-info
+ =raw flash[:info]
diff --git a/app/workers/fluentd_ui_restart.rb b/app/workers/fluentd_ui_restart.rb
new file mode 100644
index 0000000..5ce7258
--- /dev/null
+++ b/app/workers/fluentd_ui_restart.rb
@@ -0,0 +1,38 @@
+class FluentdUiRestart
+ include SuckerPunch::Job
+
+ LOCK = []
+
+ def lock!
+ raise "update process is still running" if LOCK.present?
+ LOCK << true
+ end
+
+ def unlock!
+ LOCK.shift
+ end
+
+ def perform
+ lock!
+ sleep 5 # delay for render updating HTML
+
+ # NOTE: install will be failed before released fluentd-ui gem
+ SuckerPunch.logger.info "[restart] install new fluentd-ui"
+ Plugin.new(gem_name: "fluentd-ui").install!
+
+ if Rails.env.production?
+ cmd = %W(#{Rails.root}/bin/fluentd-ui start)
+ else
+ cmd = %W(bundle exec rails s)
+ end
+
+ SuckerPunch.logger.info "[restart] will restart"
+ Bundler.with_clean_env do
+ restarter = "#{Rails.root}/bin/fluentd-ui-restart"
+ Process.spawn(*[restarter, $$.to_s, *cmd, *ARGV]) && Process.kill(:TERM, $$)
+ end
+ ensure
+ # don't reach here if restart is successful
+ unlock!
+ end
+end
diff --git a/app/workers/fluentd_ui_update_check.rb b/app/workers/fluentd_ui_update_check.rb
new file mode 100644
index 0000000..633e6c9
--- /dev/null
+++ b/app/workers/fluentd_ui_update_check.rb
@@ -0,0 +1,15 @@
+class FluentdUiUpdateCheck
+ include SuckerPunch::Job
+
+ def perform
+ pl = Plugin.new(gem_name: "fluentd-ui")
+ if pl.gem_versions # NOTE: fluentd-ui is not released yet, so `pl.latest_version` will fail for now
+ FluentdUI.latest_version = pl.latest_version
+ end
+ later(3600) # will be checked every hour
+ end
+
+ def later(sec)
+ after(sec) { perform }
+ end
+end
diff --git a/bin/fluentd-ui-restart b/bin/fluentd-ui-restart
new file mode 100755
index 0000000..3b25c45
--- /dev/null
+++ b/bin/fluentd-ui-restart
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+
+pid = ARGV.shift
+begin
+ loop do
+ # wait old fluentd-ui process shutdown
+ Process.kill(0, pid.to_i)
+ sleep 0.1
+ end
+rescue Errno::ESRCH
+ exec(*ARGV)
+end
diff --git a/config/application.rb b/config/application.rb
index b0c8fef..549f741 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -38,5 +38,7 @@ module FluentdUi
# If AR will be used, please comment in and check timezone.
# config.active_record.default_timezone = :local
# config.time_zone =
+
+ require Rails.root.join("lib", "fluentd-ui")
end
end
diff --git a/config/locales/translation_en.yml b/config/locales/translation_en.yml
index 6d6d76f..535e49d 100644
--- a/config/locales/translation_en.yml
+++ b/config/locales/translation_en.yml
@@ -3,6 +3,7 @@ en:
need_restart: need to restart fluentd-ui
please_sign_in: Sign in
destroy_succeed_fluentd_setting: Deleted fluentd setting
+ available_new_fluentd_ui: 'fluentd-ui %{version} is available. Go to system information page'
terms: &terms
sign_in: Sign in
@@ -186,6 +187,14 @@ en:
env_key: Key
env_value: Value
page_title: System Information
+ update_fluentd_ui: Update fluentd-ui
+ update_fluentd_ui_caution: "Note: fluentd will not restart"
+ update_fluentd_ui:
+ <<: *misc_common
+ update_title: Updating fluentd-ui
+ updating: Updating..
+ update_finish: Update finished!
+ failed: Failed to update. Please see fluentd-ui log
tutorials:
common: &tutorials_common
diff --git a/config/locales/translation_ja.yml b/config/locales/translation_ja.yml
index 8bcc69e..2f5b4a7 100644
--- a/config/locales/translation_ja.yml
+++ b/config/locales/translation_ja.yml
@@ -3,6 +3,7 @@ ja:
need_restart: fluentd-uiの再起動が必要です
please_sign_in: ログイン
destroy_succeed_fluentd_setting: fluentdの設定を削除しました
+ available_new_fluentd_ui: 'fluentd-ui %{version}にアップデートできます。システム情報ページへ'
terms: &terms
sign_in: ログイン
@@ -182,6 +183,14 @@ ja:
env_key: キー
env_value: 値
page_title: システム情報
+ update_fluentd_ui: fluentd-uiを更新
+ update_fluentd_ui_caution: ※fluentdは再起動されません
+ update_fluentd_ui:
+ <<: *misc_common
+ update_title: fluentd-ui 更新
+ updating: 更新中
+ update_finish: 更新が完了しました
+ failed: 更新に失敗しました。fluentd-uiのログをご確認ください
tutorials:
common: &tutorials_common
diff --git a/config/routes.rb b/config/routes.rb
index 39a586d..da70d3f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -37,6 +37,8 @@ Rails.application.routes.draw do
get "misc" => "misc#show"
get "misc/information"
+ post "misc/update_fluentd_ui"
+ get "misc/upgrading_status"
namespace :polling do
get "alerts"
diff --git a/lib/fluentd-ui.rb b/lib/fluentd-ui.rb
index ead308a..b4e001f 100644
--- a/lib/fluentd-ui.rb
+++ b/lib/fluentd-ui.rb
@@ -1,2 +1,16 @@
module FluentdUI
+ def self.latest_version=(version)
+ @latest = version
+ end
+
+ def self.latest_version
+ @latest
+ end
+
+ def self.update_available?
+ return unless @latest
+ latest = Gem::Version.new(@latest)
+ current = Gem::Version.new(::FluentdUI::VERSION)
+ latest > current
+ end
end