diff --git a/app/controllers/fluentd/settings/out_s3_controller.rb b/app/controllers/fluentd/settings/out_s3_controller.rb
new file mode 100644
index 0000000..b90240a
--- /dev/null
+++ b/app/controllers/fluentd/settings/out_s3_controller.rb
@@ -0,0 +1,34 @@
+class Fluentd::Settings::OutS3Controller < ApplicationController
+ before_action :login_required
+ before_action :find_fluentd
+
+ def show
+ @setting = Fluentd::Setting::OutS3.new({
+ s3_endpoint: "s3-us-west-1.amazonaws.com",
+ buffer_path: "/var/log/fluent/s3",
+ })
+ end
+
+ def finish
+ @setting = Fluentd::Setting::OutS3.new(setting_params)
+ unless @setting.valid?
+ return render "show"
+ end
+
+ @fluentd.agent.config_append @setting.to_conf
+ 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_s3).permit(*Fluentd::Setting::OutS3::KEYS)
+ end
+
+end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
new file mode 100644
index 0000000..133e029
--- /dev/null
+++ b/app/helpers/settings_helper.rb
@@ -0,0 +1,19 @@
+module SettingsHelper
+ def field(form, key, opts = {})
+ html = '
'
+ html << h(form.label(key))
+ html << " " # NOTE: Adding space for padding
+
+ case form.object.column_type(key)
+ when :boolean, :flag
+ html << form.check_box(key, {}, "true", "false")
+ when :choice
+ html << form.select(key, form.object.values_of(key), opts)
+ else
+ html << form.text_field(key)
+ end
+
+ html << "
"
+ html.html_safe
+ end
+end
diff --git a/app/models/fluentd/setting/common.rb b/app/models/fluentd/setting/common.rb
index 3ac5e73..321a5b3 100644
--- a/app/models/fluentd/setting/common.rb
+++ b/app/models/fluentd/setting/common.rb
@@ -1,9 +1,95 @@
class Fluentd
module Setting
module Common
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ attr_accessor :values, :types
+
+ def choice(key, values)
+ @values ||= {}
+ @values[key] = values
+ set_type(:choice, [key])
+ end
+
+ def booleans(*keys)
+ # e.g.:
+ # use_ssl true
+ # include_time_key false
+ set_type(:boolean, keys)
+ end
+
+ def flags(*keys)
+ # e.g.:
+ # tag_mapped
+ # utc
+ set_type(:flag, keys)
+ end
+
+ private
+
+ def set_type(type, keys)
+ @types ||= {}
+ keys.each do |key|
+ @types[key] = type
+ end
+ end
+ end
+
+ def values_of(key)
+ self.class.values[key] || []
+ end
+
+ def column_type(key)
+ self.class.types[key] || "string"
+ end
+
+ def conf(key)
+ case column_type(key)
+ when :boolean
+ boolenan(key)
+ when :flag
+ flag(key)
+ else
+ print_if_present(key)
+ end
+ end
+
+ def plugin_type_name
+ # Fluentd::Setting::OutS3 -> s3
+ # Override this method if not above style
+ self.class.to_s.split("::").last.sub(/(In|Out)/, "").downcase
+ end
+
def print_if_present(key)
+ # e.g.:
+ # path /var/log/td/aaa
+ # user nobody
+ # retry_limit 3
send(key).present? ? "#{key} #{send(key)}" : ""
end
+
+ def boolenan(key)
+ send(key).presence == "true" ? "#{key} true" : "#{key} false"
+ end
+
+ def flag(key)
+ send(key).presence == "true" ? key.to_s : ""
+ end
+
+ def to_config
+ indent = " "
+ config = "\n"
+ config << "#{indent}type #{plugin_type_name}\n"
+ self.class.const_get(:KEYS).each do |key|
+ next if key == :match
+ config << indent
+ config << conf(key)
+ config << "\n"
+ end
+ config << "\n"
+ config.gsub(/^[ ]*\n/m, "")
+ end
end
end
end
diff --git a/app/models/fluentd/setting/out_s3.rb b/app/models/fluentd/setting/out_s3.rb
new file mode 100644
index 0000000..b9f0a2b
--- /dev/null
+++ b/app/models/fluentd/setting/out_s3.rb
@@ -0,0 +1,33 @@
+class Fluentd
+ module Setting
+ class OutS3
+ include ActiveModel::Model
+ include Common
+
+ KEYS = [
+ :match,
+ :aws_key_id, :aws_sec_key, :s3_bucket, :s3_endpoint, :path,
+ # :reduced_redundancy, :check_apikey_on_start, :command_parameter, # not configurable?
+ :format, :include_time_key, :time_key, :delimiter, :label_delimiter, :add_newline,
+ :time_slice_format, :time_slice_wait, :time_format, :utc, :store_as, :proxy_uri, :use_ssl,
+ :buffer_type, :buffer_path, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval,
+ :retry_wait, :retry_limit, :max_retry_wait, :num_threads,
+ ].freeze
+
+ attr_accessor(*KEYS)
+
+ choice :format, %w(out_file json ltsv single_value)
+ choice :store_as, %w(gzip lzo lzma2 json txt)
+ booleans :include_time_key, :add_newline, :use_ssl
+ flags :utc
+
+ validates :match, presence: true
+ validates :s3_bucket, presence: true
+ validates :buffer_path, presence: true
+
+ def to_conf
+ to_config
+ end
+ end
+ end
+end
diff --git a/app/views/fluentd/settings/out_s3/_form.html.haml b/app/views/fluentd/settings/out_s3/_form.html.haml
new file mode 100644
index 0000000..7523f98
--- /dev/null
+++ b/app/views/fluentd/settings/out_s3/_form.html.haml
@@ -0,0 +1,39 @@
+- @setting.errors.full_messages.each do |msg|
+ = msg
+
+= form_for(@setting, url: finish_fluentd_setting_out_s3_path(@fluentd), html: {class: "ignore-rails-error-div"}) do |f|
+ = field(f, :match)
+ = field(f, :aws_key_id)
+ = field(f, :aws_sec_key)
+ = field(f, :s3_bucket)
+ = field(f, :s3_endpoint)
+ = field(f, :path)
+ = field(f, :format, prompt: "--")
+ = field(f, :time_slice_format)
+ = field(f, :time_slice_wait)
+ = field(f, :include_time_key)
+ = field(f, :utc)
+ = field(f, :delimiter)
+ = field(f, :label_delimiter)
+ = field(f, :store_as)
+ = field(f, :proxy_uri)
+ = field(f, :use_ssl)
+
+ .well.well-sm
+ %h4{"data-toggle" => "collapse", "href" => "#advanced-setting"}
+ = icon('fa-caret-down')
+ = t('terms.advanced_setting')
+ #advanced-setting.collapse
+ = field(f, :buffer_type)
+ = field(f, :buffer_path)
+ = field(f, :buffer_queue_limit)
+ = field(f, :buffer_chunk_limit)
+ = field(f, :flush_interval)
+ = field(f, :retry_wait)
+ = field(f, :retry_limit)
+ = field(f, :max_retry_wait)
+ = field(f, :num_threads)
+ = 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_s3/show.html.haml b/app/views/fluentd/settings/out_s3/show.html.haml
new file mode 100644
index 0000000..4cb594e
--- /dev/null
+++ b/app/views/fluentd/settings/out_s3/show.html.haml
@@ -0,0 +1,6 @@
+- page_title t(".page_title")
+
+.well
+ = raw t('fluentd.settings.out_td.option_guide')
+
+= render "form"
diff --git a/config/routes.rb b/config/routes.rb
index 788b1ce..e2c1bc7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -29,6 +29,10 @@ Rails.application.routes.draw do
resource :out_td, only: ["show"], module: :settings, controller: :out_td do
post "finish"
end
+
+ resource :out_s3, only: ["show"], module: :settings, controller: :out_s3 do
+ post "finish"
+ end
end
end