mirror of
https://github.com/fluent/fluentd-ui.git
synced 2025-08-15 10:47:06 +02:00
Merge pull request #16 from treasure-data/redesign_fluentd_management
[wip] fix up fluentd process management
This commit is contained in:
commit
94e1f7fd39
@ -5,7 +5,7 @@ PATH
|
||||
bcrypt (~> 3.1.5)
|
||||
bundler (~> 1.5)
|
||||
coffee-rails (~> 4.0.0)
|
||||
fluentd (= 0.10.46)
|
||||
fluentd (~> 0.10.48)
|
||||
font-awesome-rails
|
||||
haml-rails (~> 0.5.3)
|
||||
httpclient
|
||||
@ -81,14 +81,14 @@ GEM
|
||||
factory_girl_rails (4.4.1)
|
||||
factory_girl (~> 4.4.0)
|
||||
railties (>= 3.0.0)
|
||||
fluentd (0.10.46)
|
||||
fluentd (0.10.48)
|
||||
cool.io (>= 1.1.1, < 2.0.0, != 1.2.0)
|
||||
http_parser.rb (>= 0.5.1, < 0.7.0)
|
||||
json (>= 1.4.3)
|
||||
msgpack (>= 0.4.4, < 0.6.0, != 0.5.3, != 0.5.2, != 0.5.1, != 0.5.0)
|
||||
sigdump (~> 0.2.2)
|
||||
yajl-ruby (~> 1.0)
|
||||
font-awesome-rails (4.0.3.1)
|
||||
font-awesome-rails (4.1.0.0)
|
||||
railties (>= 3.2, < 5.0)
|
||||
haml (4.0.5)
|
||||
tilt
|
||||
|
37
app/controllers/fluentd/agents_controller.rb
Normal file
37
app/controllers/fluentd/agents_controller.rb
Normal file
@ -0,0 +1,37 @@
|
||||
class Fluentd::AgentsController < ApplicationController
|
||||
before_action :find_fluentd
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def start
|
||||
unless @fluentd.agent.start
|
||||
flash[:error] = t("error.fluentd_start_failed")
|
||||
end
|
||||
redirect_to fluentd_agent_path(@fluentd), status: 303 # 303 is change HTTP Verb GET
|
||||
end
|
||||
|
||||
def stop
|
||||
unless @fluentd.agent.stop
|
||||
flash[:error] = t("error.fluentd_stop_failed")
|
||||
end
|
||||
redirect_to fluentd_agent_path(@fluentd), status: 303 # 303 is change HTTP Verb GET
|
||||
end
|
||||
|
||||
def restart
|
||||
unless @fluentd.agent.restart
|
||||
flash[:error] = t("error.fluentd_restart_failed")
|
||||
end
|
||||
redirect_to fluentd_agent_path(@fluentd), status: 303 # 303 is change HTTP Verb GET
|
||||
end
|
||||
|
||||
def log
|
||||
render text: @fluentd.agent.log, content_type: "text/plain"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_fluentd
|
||||
@fluentd = Fluentd.find(params[:fluentd_id])
|
||||
end
|
||||
end
|
@ -1,32 +0,0 @@
|
||||
class Fluentd::DaemonsController < ApplicationController
|
||||
before_action :login_required
|
||||
before_action :fluentd
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def start
|
||||
fluentd.start
|
||||
render :show
|
||||
end
|
||||
|
||||
def stop
|
||||
fluentd.stop
|
||||
render :show
|
||||
end
|
||||
|
||||
def reload
|
||||
fluentd.reload
|
||||
render :show
|
||||
end
|
||||
|
||||
def log
|
||||
render text: fluentd.log, content_type: "text/plain"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fluentd
|
||||
@fluentd ||= Fluentd.new(Rails.root + "tmp" + "fluentd") # TODO
|
||||
end
|
||||
end
|
@ -1,7 +1,47 @@
|
||||
class FluentdController < ApplicationController
|
||||
before_action :login_required
|
||||
before_action :find_fluentd, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@daemons = [Fluentd.new(Rails.root + "tmp" + "fluentd")] # TODO
|
||||
@fluentds = Fluentd.all
|
||||
end
|
||||
|
||||
def new
|
||||
@fluentd = Fluentd.new(Fluentd::Agent::Fluentd::DEFAULT_OPTIONS) # TODO: not fluentd type
|
||||
end
|
||||
|
||||
def create
|
||||
@fluentd = Fluentd.new(fluentd_params)
|
||||
unless @fluentd.save
|
||||
return render :new
|
||||
end
|
||||
redirect_to fluentd_index_path
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
# TODO: should restart if changed file path? or just do "dirty" flagged?
|
||||
@fluentd.update_attributes(fluentd_params)
|
||||
unless @fluentd.save
|
||||
return render :edit
|
||||
end
|
||||
redirect_to fluentd_index_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
@fluentd.agent.stop if @fluentd.agent.running?
|
||||
@fluentd.destroy
|
||||
redirect_to fluentd_index_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_fluentd
|
||||
@fluentd = Fluentd.find(params[:id])
|
||||
end
|
||||
|
||||
def fluentd_params
|
||||
params.require(:fluentd).permit(:log_file, :pid_file, :config_file, :variant)
|
||||
end
|
||||
end
|
||||
|
@ -1,2 +0,0 @@
|
||||
module Fluentd::DaemonsHelper
|
||||
end
|
@ -1,109 +1,64 @@
|
||||
Bundler.require(:default, :development)
|
||||
class Fluentd < ActiveRecord::Base
|
||||
before_validation :expand_paths
|
||||
validates :variant, inclusion: { in: proc { Fluentd.variants } }
|
||||
validates :log_file, presence: true
|
||||
validates :pid_file, presence: true
|
||||
validates :config_file, presence: true
|
||||
validate :validate_permissions
|
||||
|
||||
require 'fluent/log'
|
||||
require 'fluent/env'
|
||||
require 'fluent/version'
|
||||
require 'fluent/supervisor'
|
||||
|
||||
class Fluentd
|
||||
attr_reader :root_dir
|
||||
|
||||
def initialize(root_dir)
|
||||
@root_dir = root_dir
|
||||
FileUtils.mkdir_p @root_dir
|
||||
def self.variants
|
||||
%w(fluentd) # TODO:
|
||||
end
|
||||
|
||||
def pid_file
|
||||
File.join(root_dir, "fluentd.pid")
|
||||
def fluentd?
|
||||
variant == "fluentd"
|
||||
end
|
||||
|
||||
def pid
|
||||
return unless File.exists?(pid_file)
|
||||
File.read(pid_file)
|
||||
def td_agent?
|
||||
variant == "td-agent"
|
||||
end
|
||||
|
||||
def log_file
|
||||
File.join(root_dir, "fluentd.log")
|
||||
end
|
||||
|
||||
def config_file
|
||||
file = File.join(root_dir, "fluentd.conf")
|
||||
unless File.exists?(file)
|
||||
File.open(file, "w") {|f| f.write "<source>\ntype forward\n</source>" } # TODO
|
||||
end
|
||||
file
|
||||
end
|
||||
|
||||
def plugin_dir
|
||||
dir = File.join(root_dir, "fluentd", "plugins")
|
||||
unless Dir.exist?(dir)
|
||||
FileUtils.mkdir_p(dir)
|
||||
end
|
||||
dir
|
||||
end
|
||||
|
||||
def options
|
||||
# TODO: https://github.com/fluent/fluentd/pull/315
|
||||
{
|
||||
:config_path => Fluent::DEFAULT_CONFIG_PATH,
|
||||
:plugin_dirs => [Fluent::DEFAULT_PLUGIN_DIR],
|
||||
:log_level => Fluent::Log::LEVEL_INFO,
|
||||
:log_path => nil,
|
||||
:daemonize => false,
|
||||
:libs => [],
|
||||
:setup_path => nil,
|
||||
:chuser => nil,
|
||||
:chgroup => nil,
|
||||
:suppress_interval => 0,
|
||||
:suppress_repeated_stacktrace => false,
|
||||
:use_v1_config => false,
|
||||
}.merge({
|
||||
:use_v1_config => true,
|
||||
:plugin_dirs => [plugin_dir],
|
||||
:config_path => config_file,
|
||||
:daemonize => pid_file,
|
||||
:log_path => log_file,
|
||||
:log_level => Fluent::Log::LEVEL_INFO,
|
||||
def agent
|
||||
klass = variant.underscore.camelize
|
||||
@agent ||= Agent.const_get(klass).new({
|
||||
:pid_file => pid_file,
|
||||
:log_file => log_file,
|
||||
:config_file => config_file,
|
||||
})
|
||||
end
|
||||
|
||||
def running?
|
||||
pid && system("/bin/kill -0 #{pid}", :out => File::NULL, :err => File::NULL)
|
||||
def expand_paths
|
||||
%w(pid_file log_file config_file).each do |column|
|
||||
path = send(column)
|
||||
next if path.blank?
|
||||
self.send("#{column}=", File.expand_path(path))
|
||||
end
|
||||
end
|
||||
|
||||
def start
|
||||
return if running?
|
||||
spawn("bundle exec fluentd #{options_to_argv(options)}") # TODO
|
||||
def validate_permissions
|
||||
%w(pid_file log_file config_file).each do |column|
|
||||
check_permission(column)
|
||||
end
|
||||
end
|
||||
|
||||
def stop
|
||||
return unless running?
|
||||
system("/bin/kill -TERM #{pid}")
|
||||
File.unlink(pid_file)
|
||||
end
|
||||
def check_permission(column)
|
||||
path = send(column)
|
||||
return if path.blank? # if empty, presence: true will catch it
|
||||
if File.exist?(path)
|
||||
if File.directory?(path)
|
||||
errors.add(column, :is_a_directory)
|
||||
end
|
||||
|
||||
def reload
|
||||
return unless running?
|
||||
system("/bin/kill -HUP #{pid}")
|
||||
end
|
||||
|
||||
def log
|
||||
File.read log_file # TODO: large log file
|
||||
end
|
||||
|
||||
def config
|
||||
::Fluentd::Configuration.new(config_file)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def options_to_argv(options)
|
||||
argv = ""
|
||||
argv << " --use-v1-config" if options[:use_v1_config]
|
||||
argv << " -c #{options[:config_path]}" if options[:config_path].present?
|
||||
argv << " -p #{options[:plugin_dir].first}" if options[:plugin_dir].present?
|
||||
argv << " -d #{options[:daemonize]}" if options[:daemonize].present?
|
||||
argv << " -o #{options[:log_path]}" if options[:log_path].present?
|
||||
argv
|
||||
unless File.writable?(path)
|
||||
errors.add(column, :lack_write_permission)
|
||||
end
|
||||
unless File.readable?(path)
|
||||
errors.add(column, :lack_read_permission)
|
||||
end
|
||||
else
|
||||
unless File.writable?(File.dirname(path))
|
||||
errors.add(column, :lack_write_permission)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
28
app/models/fluentd/agent.rb
Normal file
28
app/models/fluentd/agent.rb
Normal file
@ -0,0 +1,28 @@
|
||||
require 'fluent/log'
|
||||
require 'fluent/env'
|
||||
require 'fluent/version'
|
||||
require 'fluent/supervisor'
|
||||
require "fluentd/agent/common"
|
||||
require "fluentd/agent/fluentd"
|
||||
require "fluentd/agent/td_agent"
|
||||
require "fluentd/agent/remote"
|
||||
|
||||
class Fluentd
|
||||
class Agent
|
||||
# pidfile
|
||||
# td-agent: /var/run/td-agent/td-agent.pid
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/td-agent.logrotate#L10
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.init#L25
|
||||
# fluentd: nothing (or --daemon PIDFILE)
|
||||
#
|
||||
# logfile
|
||||
# td-agent: /var/log/td-agent/td-agent.log
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.init#L28
|
||||
# fluentd: stdout (or --log LOGFILE)
|
||||
#
|
||||
# config file
|
||||
# td-agent: /etc/td-agent/td-agent.conf
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.postinst#L69
|
||||
# fluentd: /etc/fluent/fluent.conf (by fluentd -s)
|
||||
end
|
||||
end
|
62
app/models/fluentd/agent/common.rb
Normal file
62
app/models/fluentd/agent/common.rb
Normal file
@ -0,0 +1,62 @@
|
||||
# pidfile
|
||||
# td-agent: /var/run/td-agent/td-agent.pid
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/td-agent.logrotate#L10
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.init#L25
|
||||
# fluentd: nothing (or --daemon PIDFILE)
|
||||
#
|
||||
# logfile
|
||||
# td-agent: /var/log/td-agent/td-agent.log
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.init#L28
|
||||
# fluentd: stdout (or --log LOGFILE)
|
||||
#
|
||||
# config file
|
||||
# td-agent: /etc/td-agent/td-agent.conf
|
||||
# - https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.postinst#L69
|
||||
# fluentd: /etc/fluent/fluent.conf (by fluentd -s)
|
||||
|
||||
class Fluentd
|
||||
class Agent
|
||||
module Common
|
||||
attr_reader :extra_options
|
||||
|
||||
def initialize(options = {})
|
||||
@extra_options = options
|
||||
end
|
||||
|
||||
def pid
|
||||
return unless File.exists?(pid_file)
|
||||
File.read(pid_file).to_i rescue nil
|
||||
end
|
||||
|
||||
def wait_process_starting_seconds
|
||||
10.seconds # wait time for fluentd pidfile created
|
||||
end
|
||||
|
||||
def running?
|
||||
pid && Process.kill(0, pid)
|
||||
end
|
||||
|
||||
def log
|
||||
File.read(log_file) # TODO: large log file
|
||||
end
|
||||
|
||||
def pid_file
|
||||
extra_options[:pid_file] || self.class.default_options[:pid_file]
|
||||
end
|
||||
|
||||
def log_file
|
||||
extra_options[:log_file] || self.class.default_options[:log_file]
|
||||
end
|
||||
|
||||
def config_file
|
||||
extra_options[:config_file] || self.class.default_options[:config_file]
|
||||
end
|
||||
|
||||
%w(start stop restart).each do |method|
|
||||
define_method(method) do
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
77
app/models/fluentd/agent/fluentd.rb
Normal file
77
app/models/fluentd/agent/fluentd.rb
Normal file
@ -0,0 +1,77 @@
|
||||
class Fluentd
|
||||
class Agent
|
||||
class Fluentd
|
||||
include Common
|
||||
|
||||
def self.default_options
|
||||
{
|
||||
:pid_file => "/var/run/fluent.pid",
|
||||
:log_file => "/var/log/fluent.log",
|
||||
:config_file => "/etc/fluent/fluent.conf",
|
||||
}
|
||||
end
|
||||
|
||||
def options_to_argv
|
||||
argv = ""
|
||||
argv << " --use-v1-config"
|
||||
argv << " -c #{config_file}"
|
||||
argv << " -d #{pid_file}"
|
||||
argv << " -o #{log_file}"
|
||||
argv
|
||||
end
|
||||
|
||||
def start
|
||||
return true if running?
|
||||
if validate_fluentd_options
|
||||
actual_start
|
||||
end
|
||||
end
|
||||
|
||||
def stop
|
||||
return true unless running?
|
||||
actual_stop
|
||||
end
|
||||
|
||||
def restart
|
||||
return false unless running?
|
||||
actual_restart
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_fluentd_options
|
||||
system("bundle exec fluentd --dry-run #{options_to_argv}")
|
||||
end
|
||||
|
||||
def actual_start
|
||||
spawn("bundle exec fluentd #{options_to_argv}")
|
||||
wait_starting
|
||||
end
|
||||
|
||||
def actual_stop
|
||||
if Process.kill(:TERM, pid)
|
||||
File.unlink(pid_file)
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def actual_restart
|
||||
Process.kill(:HUP, pid)
|
||||
end
|
||||
|
||||
def wait_starting
|
||||
begin
|
||||
timeout(wait_process_starting_seconds) do
|
||||
loop do
|
||||
break if pid && Process.kill(0, pid)
|
||||
sleep 0.01
|
||||
end
|
||||
end
|
||||
true
|
||||
rescue TimeoutError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
7
app/models/fluentd/agent/remote.rb
Normal file
7
app/models/fluentd/agent/remote.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class Fluentd
|
||||
class Agent
|
||||
class Remote # TODO
|
||||
include Common
|
||||
end
|
||||
end
|
||||
end
|
29
app/models/fluentd/agent/td_agent.rb
Normal file
29
app/models/fluentd/agent/td_agent.rb
Normal file
@ -0,0 +1,29 @@
|
||||
class Fluentd
|
||||
class Agent
|
||||
class TdAgent
|
||||
include Common
|
||||
|
||||
def self.default_options
|
||||
{
|
||||
:pid_file => "/var/run/td-agent/td-agent.pid",
|
||||
:log_file => "/var/log/td-agent/td-agent.log",
|
||||
:config_file => "/etc/td-agent/td-agent.conf",
|
||||
}
|
||||
end
|
||||
|
||||
def start
|
||||
system('/etc/init.d/td-agent start')
|
||||
end
|
||||
|
||||
def stop
|
||||
system('/etc/init.d/td-agent stop')
|
||||
end
|
||||
|
||||
def restart
|
||||
# NOTE: td-agent has no reload command
|
||||
# https://github.com/treasure-data/td-agent/blob/master/debian/td-agent.init#L156
|
||||
system('/etc/init.d/td-agent restart')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -86,6 +86,7 @@ class Plugin
|
||||
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
|
||||
|
18
app/views/fluentd/_form.html.haml
Normal file
18
app/views/fluentd/_form.html.haml
Normal file
@ -0,0 +1,18 @@
|
||||
%div.col-lg-6
|
||||
- @fluentd.errors.full_messages.each do |e|
|
||||
%div.alert.alert-danger= e
|
||||
|
||||
= form_for(:fluentd, url: url, method: method) do |f|
|
||||
%div.form-group
|
||||
= f.label :variant
|
||||
= f.select :variant, Fluentd.variants
|
||||
%div.form-group
|
||||
= f.label :pid_file
|
||||
= f.text_field :pid_file, class: "form-control"
|
||||
%div.form-group
|
||||
= f.label :log_file
|
||||
= f.text_field :log_file, class: "form-control"
|
||||
%div.form-group
|
||||
= f.label :config_file
|
||||
= f.text_field :config_file, class: "form-control"
|
||||
= f.submit btn, class: "btn btn-primary"
|
13
app/views/fluentd/agents/show.html.haml
Normal file
13
app/views/fluentd/agents/show.html.haml
Normal file
@ -0,0 +1,13 @@
|
||||
- page_title t('.page_title', label: "##{@fluentd.id}")
|
||||
|
||||
- if flash[:error]
|
||||
%div.alert.alert-danger= flash[:error]
|
||||
|
||||
%h4
|
||||
= @fluentd.agent.running? ? t(".running") : t(".stopped")
|
||||
|
||||
= link_to t(".start"), start_fluentd_agent_path(@fluentd), method: :put
|
||||
= link_to t(".stop"), stop_fluentd_agent_path(@fluentd), method: :put
|
||||
= link_to t(".restart"), restart_fluentd_agent_path(@fluentd), method: :put
|
||||
= link_to t(".log"), log_fluentd_agent_path(@fluentd)
|
||||
TODO: config
|
@ -1,7 +0,0 @@
|
||||
%h1
|
||||
= @fluentd.running? ? "running" : "stopped"
|
||||
|
||||
= link_to "start", start_fluentd_daemon_path(id: 1), method: :put, remote: true
|
||||
= link_to "stop", stop_fluentd_daemon_path(id: 1), method: :put, remote: true
|
||||
= link_to "reload", reload_fluentd_daemon_path(id: 1), method: :put, remote: true
|
||||
= link_to "log", log_fluentd_daemon_path(id: 1)
|
3
app/views/fluentd/edit.html.haml
Normal file
3
app/views/fluentd/edit.html.haml
Normal file
@ -0,0 +1,3 @@
|
||||
- page_title t('.page_title')
|
||||
|
||||
= render partial: "form", locals: { btn: t(".update"), url: fluentd_path(@fluentd), method: :patch }
|
@ -1,2 +1,14 @@
|
||||
- @daemons.each do |d|
|
||||
= link_to d, fluentd_daemon_path(fluentd_id: 1) # TODO
|
||||
- page_title t('.page_title')
|
||||
|
||||
%p= link_to icon('fa-plus') << " " << t(".new"), new_fluentd_path
|
||||
|
||||
- @fluentds.each do |d|
|
||||
%div.col-lg-6
|
||||
%div.panel.panel-default
|
||||
%div.panel-heading
|
||||
%h4
|
||||
= "fluentd ##{d.id}"
|
||||
= link_to t(".edit"), edit_fluentd_path(d)
|
||||
= link_to t(".destroy"), fluentd_path(d), method: :delete
|
||||
%div.panel-body
|
||||
= link_to t(".operation"), fluentd_agent_path(d) # TODO
|
||||
|
3
app/views/fluentd/new.html.haml
Normal file
3
app/views/fluentd/new.html.haml
Normal file
@ -0,0 +1,3 @@
|
||||
- page_title t('.page_title')
|
||||
|
||||
= render partial: "form", locals: { btn: t(".create"), url: fluentd_index_path, method: :post }
|
@ -2,6 +2,14 @@
|
||||
<li>
|
||||
<%= link_to_other icon("fa-dashboard fa-fw") << " Dashboard", root_path %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to_other icon("fa-puzzle-piece fa-fw") << " fluentd", fluentd_index_path %>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<%= link_to_other t("terms.new"), new_fluentd_path %>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to_other icon("fa-cogs fa-fw") << " " << t('terms.plugins') << icon('fa pull-right fa-caret-down'), plugins_path %>
|
||||
<ul class="nav nav-second-level">
|
||||
|
@ -13,6 +13,7 @@ require "sprockets/railtie"
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
# these gems are not required by Bundler.require
|
||||
require "sass"
|
||||
require "haml-rails"
|
||||
require "jquery-rails"
|
||||
require "sucker_punch"
|
||||
|
@ -16,6 +16,11 @@ ja:
|
||||
fluent_version: "fluentd %{version}"
|
||||
no_alert: なし
|
||||
update_password: パスワード更新
|
||||
create: 作成
|
||||
update: 更新
|
||||
edit: 編集
|
||||
destroy: 削除
|
||||
new: 新規作成
|
||||
|
||||
plugins:
|
||||
common: &plugin_common
|
||||
@ -45,6 +50,32 @@ ja:
|
||||
<<: *terms
|
||||
page_title: ユーザー管理
|
||||
|
||||
fluentd: &fluentd
|
||||
common: &fluentd_common
|
||||
<<: *terms
|
||||
start: 開始
|
||||
stop: 停止
|
||||
restart: 再起動
|
||||
log: ログ
|
||||
stopped: 停止中
|
||||
running: 稼働中
|
||||
operation: プロセス詳細
|
||||
form:
|
||||
<<: *fluentd_common
|
||||
index:
|
||||
<<: *fluentd_common
|
||||
page_title: fluentd
|
||||
new:
|
||||
<<: *fluentd_common
|
||||
page_title: fluentd | 追加
|
||||
edit:
|
||||
<<: *fluentd_common
|
||||
page_title: fluentd | 編集
|
||||
agents:
|
||||
show:
|
||||
<<: *fluentd_common
|
||||
page_title: "fluentd %{label}"
|
||||
|
||||
misc:
|
||||
common: &misc_common
|
||||
<<: *terms
|
||||
@ -61,11 +92,17 @@ ja:
|
||||
|
||||
error:
|
||||
login_failed: ログインに失敗しました。
|
||||
fluentd_start_failed: fluentdの起動に失敗しました。
|
||||
fluentd_stop_failed: fluentdの停止に失敗しました。
|
||||
fluentd_restart_failed: fluentdの再起動に失敗しました。
|
||||
|
||||
activerecord:
|
||||
errors:
|
||||
messages:
|
||||
wrong_password: が違います
|
||||
lack_read_permission: の読み込み権限がありません
|
||||
lack_write_permission: の書き込み権限がありません
|
||||
is_a_directory: はディレクトリです。ファイルを指定してください
|
||||
|
||||
models:
|
||||
user: user #g
|
||||
@ -78,3 +115,8 @@ ja:
|
||||
current_password: 現在のパスワード
|
||||
password: パスワード
|
||||
password_confirmation: パスワード(確認)
|
||||
fluentd:
|
||||
log_file: ログファイル
|
||||
pid_file: PIDファイル
|
||||
config_file: 設定ファイル
|
||||
variant: タイプ
|
||||
|
@ -1,11 +1,11 @@
|
||||
Rails.application.routes.draw do
|
||||
root "fluentd#index" # TODO: change to dashboard
|
||||
|
||||
resources :fluentd, only: [:index] do
|
||||
resource :daemon, only: [:show], module: :fluentd do
|
||||
resources :fluentd do
|
||||
resource :agent, only: [:show], module: :fluentd do
|
||||
put "start"
|
||||
put "stop"
|
||||
put "reload"
|
||||
put "restart"
|
||||
get "log"
|
||||
end
|
||||
resource :setting, only: [:show, :edit, :update], module: :fluentd do
|
||||
|
12
db/migrate/20140522055753_create_fluentds.rb
Normal file
12
db/migrate/20140522055753_create_fluentds.rb
Normal file
@ -0,0 +1,12 @@
|
||||
class CreateFluentds < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :fluentds do |t|
|
||||
t.string :variant, null: false # fluentd, td-agent, or remote
|
||||
t.string :pid_file
|
||||
t.string :log_file
|
||||
t.string :config_file
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
11
db/schema.rb
11
db/schema.rb
@ -11,7 +11,16 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20140522023140) do
|
||||
ActiveRecord::Schema.define(version: 20140522055753) do
|
||||
|
||||
create_table "fluentds", force: true do |t|
|
||||
t.string "variant", null: false
|
||||
t.string "pid_file"
|
||||
t.string "log_file"
|
||||
t.string "config_file"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "login_tokens", force: true do |t|
|
||||
t.string "token_id", null: false
|
||||
|
@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
spec.add_dependency "fluentd", "0.10.46"
|
||||
spec.add_dependency "fluentd", "~> 0.10.48"
|
||||
spec.add_dependency 'rails', '4.1.1'
|
||||
spec.add_dependency 'sucker_punch', "~> 1.0.5"
|
||||
spec.add_dependency 'i18n_generators', '1.2.1'
|
||||
|
8
spec/factories/fluentd.rb
Normal file
8
spec/factories/fluentd.rb
Normal file
@ -0,0 +1,8 @@
|
||||
FactoryGirl.define do
|
||||
factory :fluentd do
|
||||
variant "fluentd"
|
||||
log_file (Rails.root + "tmp/fluentd-test/fluentd.log").to_s
|
||||
pid_file (Rails.root + "tmp/fluentd-test/fluentd.pid").to_s
|
||||
config_file (Rails.root + "tmp/fluentd-test/fluentd.conf").to_s
|
||||
end
|
||||
end
|
@ -1,15 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
# Specs in this file have access to a helper object that includes
|
||||
# the MiscsHelper. For example:
|
||||
#
|
||||
# describe MiscsHelper do
|
||||
# describe "string concat" do
|
||||
# it "concats two strings with spaces" do
|
||||
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
describe MiscsHelper do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
119
spec/models/fluentd/agent_spec.rb
Normal file
119
spec/models/fluentd/agent_spec.rb
Normal file
@ -0,0 +1,119 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Fluentd::Agent do
|
||||
shared_examples_for "Agent has common behavior" do |klass|
|
||||
describe "#extra_options" do
|
||||
context "blank" do
|
||||
let(:options) { {} }
|
||||
it { instance.pid_file.should == described_class.default_options[:pid_file] }
|
||||
it { instance.log_file.should == described_class.default_options[:log_file] }
|
||||
it { instance.config_file.should == described_class.default_options[:config_file] }
|
||||
end
|
||||
|
||||
context "given" do
|
||||
let(:options) do
|
||||
{
|
||||
:pid_file => pid_file,
|
||||
:log_file => log_file,
|
||||
:config_file => config_file,
|
||||
}
|
||||
end
|
||||
let(:pid_file) { "pid" }
|
||||
let(:log_file) { "log" }
|
||||
let(:config_file) { "config" }
|
||||
|
||||
it { instance.pid_file.should == pid_file }
|
||||
it { instance.log_file.should == log_file }
|
||||
it { instance.config_file.should == config_file }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:instance) { described_class.new(options) }
|
||||
let(:options) { {} }
|
||||
|
||||
describe "Fluentd" do
|
||||
let(:described_class) { Fluentd::Agent::Fluentd } # override nested described_class behavior as https://github.com/rspec/rspec-core/issues/1114
|
||||
|
||||
it_should_behave_like "Agent has common behavior"
|
||||
|
||||
describe "#options_to_argv" do
|
||||
subject { instance.options_to_argv }
|
||||
it { should include("-c #{instance.config_file}") }
|
||||
it { should include("-d #{instance.pid_file}") }
|
||||
it { should include("-o #{instance.log_file}") }
|
||||
it { should include("--use-v1-config") }
|
||||
end
|
||||
|
||||
describe "#start" do
|
||||
before { instance.stub(:running?).and_return { running } }
|
||||
|
||||
context "running" do
|
||||
let(:running) { true }
|
||||
after { instance.start }
|
||||
|
||||
it { instance.should_not_receive(:validate_fluentd_options) }
|
||||
end
|
||||
|
||||
context "not running" do
|
||||
let(:running) { false }
|
||||
after { instance.start }
|
||||
|
||||
it { instance.should_receive(:validate_fluentd_options) }
|
||||
|
||||
context "validate_fluentd_options success" do
|
||||
before { instance.stub(:validate_fluentd_options).and_return { true } }
|
||||
it { instance.should_receive(:actual_start) }
|
||||
end
|
||||
|
||||
context "validate_fluentd_options fail" do
|
||||
before { instance.stub(:validate_fluentd_options).and_return { false } }
|
||||
it { instance.should_not_receive(:actual_start) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#stop" do
|
||||
before { instance.stub(:running?).and_return { running } }
|
||||
|
||||
context "running" do
|
||||
let(:running) { true }
|
||||
after { instance.stop }
|
||||
|
||||
it { instance.should_receive(:actual_stop) }
|
||||
end
|
||||
|
||||
context "not running" do
|
||||
let(:running) { false }
|
||||
after { instance.stop }
|
||||
|
||||
it { instance.should_not_receive(:actual_stop) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#restart" do
|
||||
before { instance.stub(:running?).and_return { running } }
|
||||
|
||||
context "running" do
|
||||
let(:running) { true }
|
||||
after { instance.restart }
|
||||
|
||||
it { instance.should_receive(:actual_restart) }
|
||||
end
|
||||
|
||||
context "not running" do
|
||||
let(:running) { false }
|
||||
after { instance.restart }
|
||||
|
||||
it { instance.should_not_receive(:actual_restart) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "TdAgent" do
|
||||
let(:described_class) { Fluentd::Agent::TdAgent } # override nested described_class behavior as https://github.com/rspec/rspec-core/issues/1114
|
||||
|
||||
it_should_behave_like "Agent has common behavior"
|
||||
end
|
||||
end
|
||||
|
127
spec/models/fluentd_spec.rb
Normal file
127
spec/models/fluentd_spec.rb
Normal file
@ -0,0 +1,127 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Fluentd do
|
||||
shared_examples_for "path permission" do |column|
|
||||
let(:path) { fluentd.send(column) }
|
||||
|
||||
subject do
|
||||
fluentd.check_permission(column)
|
||||
fluentd.errors
|
||||
end
|
||||
|
||||
context "file exists" do
|
||||
before { FileUtils.touch(path) }
|
||||
after { FileUtils.chmod(0755, path) }
|
||||
|
||||
context "writable" do
|
||||
before { FileUtils.chmod(0600, path) }
|
||||
it { should be_blank }
|
||||
end
|
||||
|
||||
context "not writable" do
|
||||
before { FileUtils.chmod(0400, path) }
|
||||
it { should_not be_blank }
|
||||
it { subject.get(column).should include(I18n.t('activerecord.errors.messages.lack_write_permission')) }
|
||||
end
|
||||
|
||||
context "not readable" do
|
||||
before { FileUtils.chmod(0200, path) }
|
||||
it { should_not be_blank }
|
||||
it { subject.get(column).should include(I18n.t('activerecord.errors.messages.lack_read_permission')) }
|
||||
end
|
||||
|
||||
context "is directory" do
|
||||
before { fluentd.send("#{column}=", Rails.root + "tmp") }
|
||||
it { should_not be_blank }
|
||||
it { subject.get(column).should include(I18n.t('activerecord.errors.messages.is_a_directory')) }
|
||||
end
|
||||
end
|
||||
|
||||
context "file not exists" do
|
||||
let(:dir) { File.dirname(path) }
|
||||
before { FileUtils.rm path }
|
||||
after { FileUtils.chmod_R(0755, dir) }
|
||||
|
||||
context "writable" do
|
||||
before { FileUtils.chmod(0700, dir) }
|
||||
it { should be_blank }
|
||||
end
|
||||
|
||||
context "not writable" do
|
||||
before { FileUtils.chmod(0500, dir) }
|
||||
it { should_not be_blank }
|
||||
it { subject.get(column).should include(I18n.t('activerecord.errors.messages.lack_write_permission')) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:fluentd) { FactoryGirl.build(:fluentd) }
|
||||
|
||||
describe "#valid?" do
|
||||
before do
|
||||
%w(pid_file log_file config_file).each do |column|
|
||||
FileUtils.mkdir_p File.dirname(fluentd.send(column))
|
||||
FileUtils.touch fluentd.send(column)
|
||||
end
|
||||
end
|
||||
|
||||
subject { fluentd }
|
||||
|
||||
describe "variant" do
|
||||
before { fluentd.variant = variant }
|
||||
|
||||
context "fluentd" do
|
||||
let(:variant) { "fluentd" }
|
||||
it { should be_valid }
|
||||
end
|
||||
|
||||
context "foobar (not declared in Fluentd.variants)" do
|
||||
let(:variant) { "foobar" }
|
||||
it { should_not be_valid }
|
||||
end
|
||||
end
|
||||
|
||||
describe "pid_file" do
|
||||
it_should_behave_like "path permission", :pid_file
|
||||
end
|
||||
|
||||
describe "log_file" do
|
||||
it_should_behave_like "path permission", :log_file
|
||||
end
|
||||
|
||||
describe "config_file" do
|
||||
it_should_behave_like "path permission", :config_file
|
||||
end
|
||||
end
|
||||
|
||||
describe "variant" do
|
||||
before { fluentd.variant = variant }
|
||||
|
||||
context "= fluentd" do
|
||||
let(:variant) { "fluentd" }
|
||||
it { fluentd.should be_fluentd }
|
||||
it { fluentd.should_not be_td_agent }
|
||||
end
|
||||
|
||||
context "= td-agent" do
|
||||
let(:variant) { "td-agent" }
|
||||
it { fluentd.should_not be_fluentd }
|
||||
it { fluentd.should be_td_agent }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#agent" do
|
||||
before { fluentd.variant = variant }
|
||||
subject { fluentd.agent }
|
||||
|
||||
context "fluentd" do
|
||||
let(:variant) { "fluentd" }
|
||||
it { should be_instance_of(Fluentd::Agent::Fluentd) }
|
||||
end
|
||||
|
||||
context "td-agent" do
|
||||
let(:variant) { "td-agent" }
|
||||
it { should be_instance_of(Fluentd::Agent::TdAgent) }
|
||||
end
|
||||
end
|
||||
end
|
@ -64,12 +64,4 @@ RSpec.configure do |config|
|
||||
config.after(:each) do
|
||||
DatabaseCleaner.clean
|
||||
end
|
||||
|
||||
config.before(:each) do
|
||||
system('sync') if ENV["CIRCLECI"] # file operations are unstable on Circle CI
|
||||
end
|
||||
|
||||
config.after(:each) do
|
||||
system('sync') if ENV["CIRCLECI"] # file operations are unstable on Circle CI
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user