From bc41fb5f4241a8391a3c468c779d6a2144dfd7e2 Mon Sep 17 00:00:00 2001 From: uu59 Date: Thu, 3 Jul 2014 16:25:08 +0900 Subject: [PATCH 1/7] Add fluentd-ui gem updates check --- app/workers/fluentd_ui_update_check.rb | 15 +++++++++++++++ lib/fluentd-ui.rb | 10 ++++++++++ 2 files changed, 25 insertions(+) create mode 100644 app/workers/fluentd_ui_update_check.rb 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/lib/fluentd-ui.rb b/lib/fluentd-ui.rb index ead308a..6cab74a 100644 --- a/lib/fluentd-ui.rb +++ b/lib/fluentd-ui.rb @@ -1,2 +1,12 @@ module FluentdUI + def self.latest_version=(version) + @latest = version + end + + def self.update_available? + return unless @latest + latest = Gem::Version.new(@latest) + current = Gem::Version.new(::FluentdUI::VERSION) + latest > current + end end From 25dda76174cc2a5505f88222563536d3cb9e32b4 Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 12:51:14 +0900 Subject: [PATCH 2/7] Restart fluentd-ui process with fluentd-ui --- app/controllers/application_controller.rb | 8 ++ app/controllers/misc_controller.rb | 20 +++++ app/views/misc/information.html.haml | 99 ++++++++++++----------- app/views/shared/_flash.html.haml | 4 +- bin/fluentd-ui-restart | 12 +++ config/application.rb | 2 + config/locales/translation_en.yml | 3 + config/locales/translation_ja.yml | 3 + config/routes.rb | 1 + lib/fluentd-ui.rb | 4 + 10 files changed, 110 insertions(+), 46 deletions(-) create mode 100755 bin/fluentd-ui-restart diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ecf823b..a682fcf 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,13 @@ class ApplicationController < ActionController::Base private + def notice_new_fluentd_ui_available + FluentdUI.latest_version = "0.3.3" # TODO: for debug, remove it later + 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..17833f2 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 + # TODO: Plugin.new(gem_name: "fluentd-ui").install + restart_fluentd_ui + # TODO: return views and polling restart finished + end + + private + + def restart_fluentd_ui + if Rails.env.production? + cmd = %W(#{Rails.root}/bin/fluentd-ui start) + else + cmd = %W(bundle exec rails s) + end + Bundler.with_clean_env do + restarter = "#{Rails.root}/bin/fluentd-ui-restart" + Process.spawn(*[restarter, $$.to_s, *cmd, *ARGV]) && Process.kill(:TERM, $$) + end + end end 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/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/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..f4072a7 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,8 @@ en: env_key: Key env_value: Value page_title: System Information + update_fluentd_ui: Update fluentd-ui + update_fluentd_ui_caution: TODO tutorials: common: &tutorials_common diff --git a/config/locales/translation_ja.yml b/config/locales/translation_ja.yml index 8bcc69e..7984571 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,8 @@ ja: env_key: キー env_value: 値 page_title: システム情報 + update_fluentd_ui: fluentd-uiを更新 + update_fluentd_ui_caution: TODO tutorials: common: &tutorials_common diff --git a/config/routes.rb b/config/routes.rb index 39a586d..a4db838 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,6 +37,7 @@ Rails.application.routes.draw do get "misc" => "misc#show" get "misc/information" + post "misc/update_fluentd_ui" namespace :polling do get "alerts" diff --git a/lib/fluentd-ui.rb b/lib/fluentd-ui.rb index 6cab74a..b4e001f 100644 --- a/lib/fluentd-ui.rb +++ b/lib/fluentd-ui.rb @@ -3,6 +3,10 @@ module FluentdUI @latest = version end + def self.latest_version + @latest + end + def self.update_available? return unless @latest latest = Gem::Version.new(@latest) From e530c1604b59fe9f726e9537998aeb6338d3fd6f Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 15:32:36 +0900 Subject: [PATCH 3/7] Add fluentd-ui updating wait page --- app/controllers/misc_controller.rb | 18 ++------------- app/views/layouts/sign_in.html.erb | 9 +------- app/views/misc/update_fluentd_ui.html.haml | 27 ++++++++++++++++++++++ app/views/sessions/new.html.haml | 21 ++++++++++------- config/locales/translation_en.yml | 7 +++++- config/locales/translation_ja.yml | 7 +++++- 6 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 app/views/misc/update_fluentd_ui.html.haml diff --git a/app/controllers/misc_controller.rb b/app/controllers/misc_controller.rb index 17833f2..dc09b40 100644 --- a/app/controllers/misc_controller.rb +++ b/app/controllers/misc_controller.rb @@ -12,21 +12,7 @@ class MiscController < ApplicationController def update_fluentd_ui # TODO: Plugin.new(gem_name: "fluentd-ui").install - restart_fluentd_ui - # TODO: return views and polling restart finished - end - - private - - def restart_fluentd_ui - if Rails.env.production? - cmd = %W(#{Rails.root}/bin/fluentd-ui start) - else - cmd = %W(bundle exec rails s) - end - Bundler.with_clean_env do - restarter = "#{Rails.root}/bin/fluentd-ui-restart" - Process.spawn(*[restarter, $$.to_s, *cmd, *ARGV]) && Process.kill(:TERM, $$) - end + FluentdUiRestart.new.async.perform + render "update_fluentd_ui", layout: "sign_in" end 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 @@
- + <%= yield %>
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..65068f1 --- /dev/null +++ b/app/views/misc/update_fluentd_ui.html.haml @@ -0,0 +1,27 @@ +.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') + = link_to "Home", root_path + +:javascript + function ping() { + setTimeout(function(){ + jQuery.ajax({ + url: "/", + type: "HEAD" + }) + .fail(ping) + .done(function(response, message, jqXhr){ + jQuery('#processing').hide(); + jQuery('#finished').show(); + }); + }, 512); + } + 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/config/locales/translation_en.yml b/config/locales/translation_en.yml index f4072a7..11104ce 100644 --- a/config/locales/translation_en.yml +++ b/config/locales/translation_en.yml @@ -188,7 +188,12 @@ en: env_value: Value page_title: System Information update_fluentd_ui: Update fluentd-ui - update_fluentd_ui_caution: TODO + 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! tutorials: common: &tutorials_common diff --git a/config/locales/translation_ja.yml b/config/locales/translation_ja.yml index 7984571..013bfe3 100644 --- a/config/locales/translation_ja.yml +++ b/config/locales/translation_ja.yml @@ -184,7 +184,12 @@ ja: env_value: 値 page_title: システム情報 update_fluentd_ui: fluentd-uiを更新 - update_fluentd_ui_caution: TODO + update_fluentd_ui_caution: ※fluentdは再起動されません + update_fluentd_ui: + <<: *misc_common + update_title: fluentd-ui 更新 + updating: 更新中 + update_finish: 更新が完了しました tutorials: common: &tutorials_common From 82a5cce4bd60afe62a3e86090101caed50719ba6 Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 17:32:45 +0900 Subject: [PATCH 4/7] Add failed route to waiting update page --- app/controllers/misc_controller.rb | 16 ++++++++- app/views/misc/update_fluentd_ui.html.haml | 34 ++++++++++++++----- app/workers/fluentd_ui_restart.rb | 38 ++++++++++++++++++++++ config/locales/translation_en.yml | 1 + config/locales/translation_ja.yml | 1 + config/routes.rb | 1 + 6 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 app/workers/fluentd_ui_restart.rb diff --git a/app/controllers/misc_controller.rb b/app/controllers/misc_controller.rb index dc09b40..6a71c33 100644 --- a/app/controllers/misc_controller.rb +++ b/app/controllers/misc_controller.rb @@ -11,8 +11,22 @@ class MiscController < ApplicationController end def update_fluentd_ui - # TODO: Plugin.new(gem_name: "fluentd-ui").install 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/views/misc/update_fluentd_ui.html.haml b/app/views/misc/update_fluentd_ui.html.haml index 65068f1..f6b4b2b 100644 --- a/app/views/misc/update_fluentd_ui.html.haml +++ b/app/views/misc/update_fluentd_ui.html.haml @@ -5,23 +5,41 @@ #processing = icon('fa-lg fa-gear fa-spin') = t('.updating') - #finished{style: "display:none"} + #finished{style: "display: none"} = icon('fa-lg fa-check') = t('.update_finish') - = link_to "Home", root_path + %p= link_to t('misc.information.page_title'), misc_information_path + #failed{style: "display: none"} + = icon('fa-lg fa-fail') + = 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: "/", - type: "HEAD" + url: "#{misc_upgrading_status_path}", + type: "GET", + data: { old_pid: CURRENT_PID } }) .fail(ping) - .done(function(response, message, jqXhr){ - jQuery('#processing').hide(); - jQuery('#finished').show(); + .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; + } }); - }, 512); + }, 3000); } ping(); 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/config/locales/translation_en.yml b/config/locales/translation_en.yml index 11104ce..535e49d 100644 --- a/config/locales/translation_en.yml +++ b/config/locales/translation_en.yml @@ -194,6 +194,7 @@ en: 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 013bfe3..2f5b4a7 100644 --- a/config/locales/translation_ja.yml +++ b/config/locales/translation_ja.yml @@ -190,6 +190,7 @@ ja: 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 a4db838..da70d3f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -38,6 +38,7 @@ 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" From babb3df89c747b268cef908b18fe667d0c982687 Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 18:28:19 +0900 Subject: [PATCH 5/7] Remove debug code --- app/controllers/application_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a682fcf..23fa7b9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -52,7 +52,6 @@ class ApplicationController < ActionController::Base private def notice_new_fluentd_ui_available - FluentdUI.latest_version = "0.3.3" # TODO: for debug, remove it later if FluentdUI.update_available? flash[:info] = I18n.t("messages.available_new_fluentd_ui", version: FluentdUI.latest_version, update_url: misc_information_path) end From 5c432c3d0f1ba7f1e4c2827d63fdaa4e76b97bd9 Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 18:28:41 +0900 Subject: [PATCH 6/7] Don't record fluentd-ui gem update --- app/models/plugin.rb | 2 ++ 1 file changed, 2 insertions(+) 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 From 64f07160d547166eaedf4e1cec13743830d1f4b9 Mon Sep 17 00:00:00 2001 From: uu59 Date: Fri, 4 Jul 2014 18:31:48 +0900 Subject: [PATCH 7/7] Fix failed icon to be sure --- app/views/misc/update_fluentd_ui.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/misc/update_fluentd_ui.html.haml b/app/views/misc/update_fluentd_ui.html.haml index f6b4b2b..4d345bb 100644 --- a/app/views/misc/update_fluentd_ui.html.haml +++ b/app/views/misc/update_fluentd_ui.html.haml @@ -10,7 +10,7 @@ = t('.update_finish') %p= link_to t('misc.information.page_title'), misc_information_path #failed{style: "display: none"} - = icon('fa-lg fa-fail') + = icon('fa-lg fa-exclamation-circle') = t('.failed') %p= link_to t('misc.information.page_title'), misc_information_path