diff --git a/app/assets/javascripts/nested_setting.js b/app/assets/javascripts/nested_setting.js
new file mode 100644
index 0000000..ad94241
--- /dev/null
+++ b/app/assets/javascripts/nested_setting.js
@@ -0,0 +1,7 @@
+(function(){
+ "use strict";
+
+ $(function(){
+ });
+})();
+
diff --git a/app/assets/stylesheets/common.css.scss b/app/assets/stylesheets/common.css.scss
index 6144ce4..1fc429a 100644
--- a/app/assets/stylesheets/common.css.scss
+++ b/app/assets/stylesheets/common.css.scss
@@ -123,3 +123,9 @@ label {
display: inline;
}
}
+
+.form-group {
+ .form-group {
+ margin-left: 30px; // used at fluentd/settings/out_forward, nested config form
+ }
+}
diff --git a/app/controllers/fluentd/settings/out_forward_controller.rb b/app/controllers/fluentd/settings/out_forward_controller.rb
new file mode 100644
index 0000000..f449a31
--- /dev/null
+++ b/app/controllers/fluentd/settings/out_forward_controller.rb
@@ -0,0 +1,34 @@
+class Fluentd::Settings::OutForwardController < ApplicationController
+ before_action :login_required
+ before_action :find_fluentd
+
+ def show
+ @setting = Fluentd::Setting::OutForward.new({
+ })
+ end
+
+ def finish
+ @setting = Fluentd::Setting::OutForward.new(setting_params)
+ unless @setting.valid?
+ return render "show"
+ end
+
+ @fluentd.agent.config_append @setting.to_config
+ if @fluentd.agent.running?
+ unless @fluentd.agent.restart
+ @setting.errors.add(:base, @fluentd.agent.log_tail(1).first)
+ return render "show"
+ end
+ end
+ redirect_to fluentd_setting_path(@fluentd)
+ end
+
+ private
+
+ def setting_params
+ params.require(:fluentd_setting_out_forward).permit(*Fluentd::Setting::OutForward::KEYS).merge(
+ params.require(:fluentd_setting_out_forward).permit(:server => Fluentd::Setting::OutForward::Server::KEYS)
+ )
+ end
+
+end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index 133e029..dab9248 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -9,6 +9,18 @@ module SettingsHelper
html << form.check_box(key, {}, "true", "false")
when :choice
html << form.select(key, form.object.values_of(key), opts)
+ when :nested
+ child_data = form.object.class.children[key]
+ klass = child_data[:class]
+ children = form.object.send(key) || {"0" => {}}
+ children.each_pair do |index, child|
+ # TODO: allow append/delete for multiple child
+ form.fields_for("#{key}[#{index}]", klass.new(child), class: "nested-column #{child_data[:multiple] ? "multiple" : ""} well well-sm") do |ff|
+ klass::KEYS.each do |k|
+ html << field(ff, k)
+ end
+ end
+ end
else
html << form.text_field(key)
end
diff --git a/app/models/fluentd/setting/common.rb b/app/models/fluentd/setting/common.rb
index 321a5b3..cfa7c8d 100644
--- a/app/models/fluentd/setting/common.rb
+++ b/app/models/fluentd/setting/common.rb
@@ -2,9 +2,10 @@ class Fluentd
module Setting
module Common
extend ActiveSupport::Concern
+ include ActiveModel::Model
module ClassMethods
- attr_accessor :values, :types
+ attr_accessor :values, :types, :children
def choice(key, values)
@values ||= {}
@@ -12,6 +13,22 @@ class Fluentd
set_type(:choice, [key])
end
+ def nested(key, klass, options = {})
+ # e.g.:
+ #
+ # type forward
+ #
+ # ..
+ #
+ #
+ @children ||= {}
+ @children[key] = {
+ class: klass,
+ options: options,
+ }
+ set_type(:nested, [key])
+ end
+
def booleans(*keys)
# e.g.:
# use_ssl true
@@ -36,12 +53,16 @@ class Fluentd
end
end
+ def child_class(key)
+ self.class.children[key][:class]
+ end
+
def values_of(key)
- self.class.values[key] || []
+ self.class.values.try(:[], key) || []
end
def column_type(key)
- self.class.types[key] || "string"
+ self.class.types.try(:[], key) || "string"
end
def conf(key)
@@ -50,6 +71,26 @@ class Fluentd
boolenan(key)
when :flag
flag(key)
+ when :nested
+ klass = child_class(key)
+ send(key).map do |(_, child)|
+ # send("servers")
+ #
+ # "servers" => {
+ # "0" => {
+ # "name" => "foo",
+ # "host" => "bar",
+ # ..
+ # },
+ # "1" => {
+ # ..
+ # }
+ # }
+ child_instance = klass.new(child)
+ unless child_instance.empty_value?
+ "\n" + child_instance.to_config(key).gsub(/^/m, " ")
+ end
+ end.join
else
print_if_present(key)
end
@@ -77,17 +118,33 @@ class Fluentd
send(key).presence == "true" ? key.to_s : ""
end
- def to_config
+ def empty_value?
+ config = ""
+ self.class.const_get(:KEYS).each do |key|
+ config << conf(key)
+ end
+ config.empty?
+ end
+
+ def to_config(elm_name = nil)
indent = " "
- config = "\n"
- config << "#{indent}type #{plugin_type_name}\n"
+ if elm_name
+ config = "<#{elm_name}>\n"
+ else
+ config = "\n"
+ config << "#{indent}type #{plugin_type_name}\n"
+ end
self.class.const_get(:KEYS).each do |key|
next if key == :match
config << indent
config << conf(key)
config << "\n"
end
- config << "\n"
+ if elm_name
+ config << "#{elm_name}>\n"
+ else
+ config << "\n"
+ end
config.gsub(/^[ ]*\n/m, "")
end
end
diff --git a/app/models/fluentd/setting/out_forward.rb b/app/models/fluentd/setting/out_forward.rb
new file mode 100644
index 0000000..711f40e
--- /dev/null
+++ b/app/models/fluentd/setting/out_forward.rb
@@ -0,0 +1,48 @@
+class Fluentd
+ module Setting
+ class OutForward
+ class Server
+ include Common
+ KEYS = [
+ :name, :host, :port, :weight, :standby
+ ].freeze
+
+ attr_accessor(*KEYS)
+
+ flags :standby
+
+ validates :host, presence: true
+ end
+
+ include Common
+
+ KEYS = [
+ :match,
+ :send_timeout, :recover_wait, :heartbeat_type, :heartbeat_interval,
+ :phi_threshold, :hard_timeout,
+ :server
+ ].freeze
+
+ attr_accessor(*KEYS)
+ choice :heartbeat_type, %w(udp tcp)
+ nested :server, Server
+
+ validates :match, presence: true
+ validate :validate_at_least_one_server
+ validate :validate_nested_values
+
+ def validate_at_least_one_server
+ # FIXME: real validation
+ true
+ end
+
+ def validate_nested_values
+ # FIXME: real validation with child class instance
+ self.class.children.inject(true) do |result, child|
+ # result & child.valid?
+ end
+ true
+ end
+ end
+ end
+end
diff --git a/app/views/fluentd/settings/out_forward/_form.html.haml b/app/views/fluentd/settings/out_forward/_form.html.haml
new file mode 100644
index 0000000..25209a4
--- /dev/null
+++ b/app/views/fluentd/settings/out_forward/_form.html.haml
@@ -0,0 +1,22 @@
+- @setting.errors.full_messages.each do |msg|
+ = msg
+
+= form_for(@setting, url: finish_fluentd_setting_out_forward_path(@fluentd), html: {class: "ignore-rails-error-div"}) do |f|
+ = field(f, :match)
+ = field(f, :server)
+
+ .well.well-sm
+ %h4{"data-toggle" => "collapse", "href" => "#advanced-setting"}
+ = icon('fa-caret-down')
+ = t('terms.advanced_setting')
+ #advanced-setting.collapse
+ = field(f, :send_timeout)
+ = field(f, :recover_wait)
+ = field(f, :heartbeat_type)
+ = field(f, :heartbeat_interval)
+ = field(f, :phi_threshold)
+ = field(f, :hard_timeout)
+ = f.submit t('fluentd.common.finish') , class: "btn btn-lg btn-primary pull-right"
+ = f.submit t('terms.prev'), class: "btn btn-lg btn-default", name: "back"
+
+
diff --git a/app/views/fluentd/settings/out_forward/show.html.haml b/app/views/fluentd/settings/out_forward/show.html.haml
new file mode 100644
index 0000000..c959242
--- /dev/null
+++ b/app/views/fluentd/settings/out_forward/show.html.haml
@@ -0,0 +1,6 @@
+- page_title t(".page_title")
+
+.well
+ = raw t('fluentd.settings.out_forward.option_guide')
+
+= render "form"
diff --git a/app/views/fluentd/settings/show.html.haml b/app/views/fluentd/settings/show.html.haml
index dc99ae5..163f939 100644
--- a/app/views/fluentd/settings/show.html.haml
+++ b/app/views/fluentd/settings/show.html.haml
@@ -36,3 +36,7 @@
= link_to(fluentd_setting_out_mongo_path(@fluentd)) do
= icon('fa-file-text-o fa-lg')
= t("fluentd.common.setup_out_mongo")
+ %p
+ = link_to(fluentd_setting_out_forward_path(@fluentd)) do
+ = icon('fa-file-text-o fa-lg')
+ = t("fluentd.common.setup_out_forward")
diff --git a/config/locales/translation_en.yml b/config/locales/translation_en.yml
index e7d9f4c..df15607 100644
--- a/config/locales/translation_en.yml
+++ b/config/locales/translation_en.yml
@@ -96,6 +96,7 @@ en:
setup_in_syslog: Setting Syslog readling
setup_out_td: Setting Treasure Data writing
setup_out_mongo: Setting MongoDB writing
+ setup_out_forward: forward(TODO)
finish: Update config
fluentd_info: Setting info
recent_errors: "Recently %{days} days errors"
@@ -128,9 +129,12 @@ en:
out: Output source setting
edit:
<<: *fluentd_common
+ out_forward:
+ option_guide: |
+ show:
+ page_title: out_forward(TODO)
out_td:
option_guide: |
- fluent-plugin-td install is required.
show:
page_title: Write to Treasure Data setting
out_mongo:
diff --git a/config/locales/translation_ja.yml b/config/locales/translation_ja.yml
index 904fa28..524f788 100644
--- a/config/locales/translation_ja.yml
+++ b/config/locales/translation_ja.yml
@@ -96,6 +96,7 @@ ja:
setup_in_syslog: syslog読み込みの設定
setup_out_td: Treasure Dataへの書き出し設定
setup_out_mongo: MongoDBへの書き出し設定
+ setup_out_forward: forward(TODO)
finish: 設定する
fluentd_info: 設定情報
recent_errors: "直近 %{days} 日内のエラー"
@@ -129,6 +130,10 @@ ja:
out: 出力ソースの設定
edit:
<<: *fluentd_common
+ out_forward:
+ option_guide: |
+ show:
+ page_title: out_forward(TODO)
out_td:
option_guide: |
fluent-plugin-tdプラグインのインストールが必要です。
diff --git a/config/routes.rb b/config/routes.rb
index e2c1bc7..b944f7a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -33,6 +33,10 @@ Rails.application.routes.draw do
resource :out_s3, only: ["show"], module: :settings, controller: :out_s3 do
post "finish"
end
+
+ resource :out_forward, only: ["show"], module: :settings, controller: :out_forward do
+ post "finish"
+ end
end
end