Merge pull request #37 from treasure-data/self_update

Self update
This commit is contained in:
uu59 2014-07-04 18:38:35 +09:00
commit 959c2b2bc1
16 changed files with 246 additions and 62 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -18,14 +18,7 @@
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><%= t('messages.please_sign_in') %></h3>
</div>
<div class="panel-body">
<%= yield %>
</div>
</div>
<%= yield %>
</div>
</div>
</div>

View File

@ -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() {

View File

@ -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();

View File

@ -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"

View File

@ -5,4 +5,6 @@
- if flash[:success]
%p.alert.alert-success
=raw flash[:success]
- if flash[:info]
%p.alert.alert-info
=raw flash[:info]

View File

@ -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

View File

@ -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

12
bin/fluentd-ui-restart Executable file
View File

@ -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

View File

@ -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

View File

@ -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. <a href="%{update_url}">Go to system information page</a>'
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

View File

@ -3,6 +3,7 @@ ja:
need_restart: fluentd-uiの再起動が必要です
please_sign_in: ログイン
destroy_succeed_fluentd_setting: fluentdの設定を削除しました
available_new_fluentd_ui: 'fluentd-ui %{version}にアップデートできます。<a href="%{update_url}">システム情報ページへ</a>'
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

View File

@ -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"

View File

@ -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