fluentd-server 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 27858b7cd48db1e7cad5f4b2d1f10724b863f103
4
- data.tar.gz: 0d0ed73cd1cc881632cafdcefb546b9a9071f3b0
3
+ metadata.gz: 29880280e87c05f7108661ac476c81546ad0f5b6
4
+ data.tar.gz: 9d375e9b51d467ffadebf388991dab55a267d943
5
5
  SHA512:
6
- metadata.gz: bfb1a7297aa0c1f929966fa330060ba52c0ddc207418abf9cf6de97c2b6ac00ad2fb7ef449c833531706f4008755c1fbca69466460d19131defbc9e1f99e9140
7
- data.tar.gz: dc2dc999877f2f215d3ab65ee29823697e6429690a150b89ad8da5e12b273ce72519dff4299130f0aad8d93e94fe556a3328e00867e18aa98a5c0ec7b4fdbd36
6
+ metadata.gz: 94c767cc074eaf54d61b60b21bd472ab20545bb39e35c41bbbc9742f5c148d9a8a2bfc0a1e68be936a28a6dddddf9d653087c71ceeef31c83262b67c4c7319bf
7
+ data.tar.gz: b7c46262f055be84c81a4205ec496022188bbc4923b1bd49a1d5919c65d30fb3b931a7194464c3668e35fbca60db03eddeeb15315d62a2d88dcf0a63c142f10b
data/.env CHANGED
@@ -6,3 +6,6 @@ HOST=0.0.0.0
6
6
  # LOG_LEVEL=debug
7
7
  # LOG_SHIFT_AGE=0
8
8
  # LOG_SHIFT_SIZE=1048576
9
+ # LOCAL_STORAGE=false
10
+ # DATA_DIR=data
11
+ # SYNC_INTERVAL=60
data/.travis.yml CHANGED
@@ -4,5 +4,5 @@ rvm:
4
4
  gemfile:
5
5
  - Gemfile
6
6
  env:
7
- - DATA_DIR=
8
- - DATA_DIR=spec/tmp
7
+ - LOCAL_STORAGE=false
8
+ - LOCAL_STORAGE=true DATA_DIR=spec/tmp
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # 0.3.0
2
+
3
+ Enhancements:
4
+
5
+ * Add sync_worker
6
+
7
+ Changes:
8
+
9
+ * Use env LOCAL_STORAGE rather than DATA_DIR to enable local file storage feature
10
+
1
11
  # 0.2.0
2
12
 
3
13
  Enhancements:
data/Procfile CHANGED
@@ -1,3 +1,4 @@
1
1
  web: bundle exec unicorn -E production -p $PORT -o $HOST -c config/unicorn.conf
2
2
  job: bundle exec bin/fluentd-server job
3
+ sync: bundle exec bin/fluentd-server sync
3
4
  serf: $(bundle exec gem path serf-td-agent)/bin/serf agent
data/README.md CHANGED
@@ -100,18 +100,28 @@ HOST=0.0.0.0
100
100
  # LOG_LEVEL=debug
101
101
  # LOG_SHIFT_AGE=0
102
102
  # LOG_SHIFT_SIZE=1048576
103
+ # LOCAL_STORAGE=false
104
+ # DATA_DIR=data
105
+ # SYNC_INTERVAL=60
103
106
  ```
104
107
 
105
- ### DATA_DIR (experimental)
108
+ ### LOCAL FILE STORAGE
106
109
 
107
- Configure `DATA_DIR` in `.env` file as:
110
+ Fluentd Server also supports to edit Fluentd configuration files as local files for the case using `git` (or any VCSs) to manage Fluentd configuration revisions.
111
+
112
+ To use this feature, enable `LOCAL_STORAGE` in `.env` file:
108
113
 
109
114
  ```
115
+ LOCAL_STORAGE=true
110
116
  DATA_DIR=data
117
+ SYNC_INTERVAL=60
111
118
  ```
112
119
 
113
- to store and load Fluentd config contents not from DB, but from local files located at the directory `DATA_DIR`.
114
- This would be useful when you want to manage your config files with git.
120
+ The `DATA_DIR` is the location to place your configuration files locally, and the `SYNC_INTERVAL` is the interval where a synchronization worker works.
121
+
122
+ Putting any files whose name ends with `.erb` in `DATA_DIR` automatically synchronizes with DB by the `sync` worker. Removing `.erb` files is also synchronized with DB.
123
+
124
+ NOTE: Enabling this feature disables to edit the Fluentd configuration from the Web UI.
115
125
 
116
126
  ## HTTP API
117
127
 
@@ -119,7 +129,6 @@ See [API.md](API.md).
119
129
 
120
130
  ## ToDo
121
131
 
122
- * Create a sync worker to synchronize local file existences with db (delete and create entries on db).
123
132
  * Automatic deployment (restart) support like the one of chef-server
124
133
 
125
134
  ## ChangeLog
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rspec"
22
+ spec.add_development_dependency "rspec", "~> 3"
23
23
  spec.add_development_dependency "capybara"
24
24
  spec.add_development_dependency "pry"
25
25
  spec.add_development_dependency "pry-nav"
@@ -23,11 +23,15 @@ LOG_PATH=#{LOG_FILE}
23
23
  LOG_LEVEL=warn
24
24
  LOG_SHIFT_AGE=0
25
25
  LOG_SHIFT_SIZE=1048576
26
+ LOCAL_STORAGE=false
27
+ DATA_DIR=#{DATA_DIR}
28
+ SYNC_INTERVAL=60
26
29
  EOS
27
30
 
28
31
  DEFAULT_PROCFILE =<<-EOS
29
32
  web: unicorn -E production -p $PORT -o $HOST -c config/unicorn.conf
30
33
  job: fluentd-server job
34
+ sync: fluentd-server sync
31
35
  serf: $(gem path serf-td-agent)/bin/serf agent
32
36
  EOS
33
37
 
@@ -105,6 +109,13 @@ EOS
105
109
  Delayed::Job.delete_all
106
110
  end
107
111
 
112
+ desc "sync", "Sartup fluentd_server sync worker"
113
+ def sync
114
+ Dotenv.load
115
+ require 'fluentd_server/sync_worker'
116
+ FluentdServer::SyncWorker.start
117
+ end
118
+
108
119
  no_tasks do
109
120
  def abort(msg)
110
121
  $stderr.puts msg
@@ -5,10 +5,6 @@ require 'dotenv'
5
5
  Dotenv.load
6
6
 
7
7
  module FluentdServer::Config
8
- def self.data_dir
9
- ENV['DATA_DIR'] == "" ? nil : ENV['DATA_DIR']
10
- end
11
-
12
8
  def self.database_url
13
9
  ENV.fetch('DATABASE_URL', 'sqlite3:data/fluentd_server.db')
14
10
  end
@@ -36,4 +32,16 @@ module FluentdServer::Config
36
32
  def self.task_max_num
37
33
  ENV.fetch('TASK_MAX_NUM', '20').to_i
38
34
  end
35
+
36
+ def self.local_storage
37
+ ENV.fetch('LOCAL_STORAGE', 'false') == 'true' ? true : false
38
+ end
39
+
40
+ def self.data_dir
41
+ ENV.fetch('DATA_DIR', 'data')
42
+ end
43
+
44
+ def self.sync_interval
45
+ ENV.fetch('SYNC_INTERVAL', '60').to_i
46
+ end
39
47
  end
@@ -11,9 +11,8 @@ class Post < ActiveRecord::Base
11
11
  include FluentdServer::Logger
12
12
 
13
13
  validates :name, presence: true
14
- validates :body, presence: true
15
14
 
16
- if FluentdServer::Config.data_dir
15
+ if FluentdServer::Config.local_storage
17
16
  include ActsAsFile
18
17
 
19
18
  def filename
@@ -0,0 +1,70 @@
1
+ require 'fluentd_server/model'
2
+ require 'fluentd_server/logger'
3
+
4
+ class FluentdServer::SyncRunner
5
+ include FluentdServer::Logger
6
+
7
+ def self.run(opts = {})
8
+ self.new(opts).run
9
+ end
10
+
11
+ def initialize(opts = {})
12
+ end
13
+
14
+ def run
15
+ return nil unless FluentdServer::Config.local_storage
16
+ plus, minus = find_diff
17
+ create(plus)
18
+ delete(minus)
19
+ end
20
+
21
+ def find_locals
22
+ return [] unless FluentdServer::Config.local_storage
23
+ names = []
24
+ Dir.chdir(FluentdServer::Config.data_dir) do
25
+ Dir.glob("*.erb") do |filename|
26
+ names << filename.chomp('.erb')
27
+ end
28
+ end
29
+ names
30
+ end
31
+
32
+ def create(names)
33
+ # ToDo: bulk insert with sqlite, postgresql? use activerecord-import for mysql2
34
+ logger.debug "[sync] create #{names}"
35
+ names.each do |name|
36
+ begin
37
+ Post.create(name: name)
38
+ rescue ActiveRecord::RecordNotUnique => e
39
+ logger.debug "#{e.class} #{e.message} #{name}"
40
+ rescue => e
41
+ logger.warn "#{e.class} #{e.message} #{name}"
42
+ end
43
+ end
44
+ end
45
+
46
+ def delete(names)
47
+ logger.debug "[sync] remove #{names}"
48
+ begin
49
+ Post.where(:name => names).delete_all
50
+ rescue => e
51
+ logger.warn "#{e.class} #{e.message} #{names}"
52
+ end
53
+ end
54
+
55
+ # Find difference between given array of paths and paths stored in DB
56
+ #
57
+ # @param [Integer] batch_size The batch size of a select query
58
+ # @return [Array] Plus (array) and minus (array) differences
59
+ def find_diff(batch_size: 1000)
60
+ names = find_locals
61
+ plus = names
62
+ minus = []
63
+ Post.select('id, name').find_in_batches(batch_size: batch_size) do |batches|
64
+ batches = batches.map(&:name)
65
+ plus -= batches
66
+ minus += (batches - names)
67
+ end
68
+ [plus, minus]
69
+ end
70
+ end
@@ -0,0 +1,81 @@
1
+ require "fluentd_server/config"
2
+ require "fluentd_server/logger"
3
+ require "fluentd_server/sync_runner"
4
+
5
+ # reference: https://github.com/focuslight/focuslight/blob/master/lib/focuslight/worker.rb
6
+ # thanks!
7
+ class FluentdServer::SyncWorker
8
+ include FluentdServer::Logger
9
+
10
+ DEFAULT_INTERVAL = 60
11
+ attr_reader :interval
12
+
13
+ def self.start(opts = {})
14
+ self.new(opts).start
15
+ end
16
+
17
+ def initialize(opts = {})
18
+ @opts = opts
19
+ @interval = opts[:interval] || FluentdServer::Config.sync_interval || DEFAULT_INTERVAL
20
+ @signals = []
21
+ end
22
+
23
+ def update_next!
24
+ now = Time.now
25
+ @next_time = now - ( now.to_i % @interval ) + @interval
26
+ end
27
+
28
+ def start
29
+ Signal.trap(:INT){ @signals << :INT }
30
+ Signal.trap(:HUP){ @signals << :HUP }
31
+ Signal.trap(:TERM){ @signals << :TERM }
32
+ Signal.trap(:PIPE, "IGNORE")
33
+
34
+ update_next!
35
+ logger.info("[sync] first updater start in #{@next_time}")
36
+
37
+ childpid = nil
38
+ while sleep(0.5) do
39
+ if childpid
40
+ begin
41
+ if Process.waitpid(childpid, Process::WNOHANG)
42
+ #TODO: $? (Process::Status object)
43
+ logger.debug("[sync] update finished pid: #{childpid}, code: #{$? >> 8}")
44
+ logger.debug("[sync] next updater start in #{@next_time}")
45
+ childpid = nil
46
+ end
47
+ rescue Errno::ECHILD
48
+ logger.warn("[sync] no child process");
49
+ childpid = nil
50
+ end
51
+ end
52
+
53
+ unless @signals.empty?
54
+ logger.warn("[sync] signals_received: #{@signals.join(',')}")
55
+ break
56
+ end
57
+
58
+ next if Time.now < @next_time
59
+ update_next!
60
+ logger.debug("[sync] (#{@next_time}) updater start")
61
+
62
+ if childpid
63
+ logger.warn("[sync] previous updater exists, skipping this time")
64
+ next
65
+ end
66
+
67
+ childpid = fork do
68
+ FluentdServer::SyncRunner.run(@opts)
69
+ end
70
+ end
71
+
72
+ if childpid
73
+ logger.warn("[sync] waiting for updater process finishing")
74
+ begin
75
+ waitpid childpid
76
+ rescue Errno::ECHILD
77
+ # ignore
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,3 +1,3 @@
1
1
  module FluentdServer
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/spec/model_spec.rb CHANGED
@@ -11,8 +11,8 @@ describe Task do
11
11
  after { Task.delete_all }
12
12
 
13
13
  context '#new?' do
14
- it { expect(Task.new.new?).to be_true }
15
- it { expect(Task.create.new?).to be_false }
14
+ it { expect(Task.new.new?).to be_truthy }
15
+ it { expect(Task.create.new?).to be_falsey }
16
16
  end
17
17
 
18
18
  context '#filename' do
@@ -21,7 +21,7 @@ describe Task do
21
21
  end
22
22
 
23
23
  context '#create_and_delete' do
24
- before { FluentdServer::Config.stub(:task_max_num).and_return(1) }
24
+ before { allow(FluentdServer::Config).to receive(:task_max_num).and_return(1) }
25
25
  before { @oldest = Task.create(name: 'Restart') }
26
26
  it {
27
27
  Task.create_and_delete(name: 'Restart')
@@ -0,0 +1,77 @@
1
+ require_relative 'spec_helper'
2
+ require 'fluentd_server/sync_runner'
3
+
4
+ if FluentdServer::Config.local_storage
5
+ describe 'SyncRunner' do
6
+ around {
7
+ filenames = File.join(FluentdServer::Config.data_dir, '*.erb')
8
+ Dir.glob(filenames).each { |f| File.delete(f) rescue nil }
9
+ Post.delete_all
10
+ }
11
+ let(:runner) { FluentdServer::SyncRunner.new }
12
+
13
+ context '#find_locals' do
14
+ before { Post.create(name: 'post1') }
15
+ before { Post.create(name: 'post2') }
16
+ let(:subject) { runner.find_locals }
17
+ it { should =~ ['post1', 'post2' ] }
18
+ end
19
+
20
+ context '#find_diff' do
21
+ before { Post.new(name: 'post1').save_without_file }
22
+ before { Post.create(name: 'post2') }
23
+ before { File.open(Post.new(name: 'post3').filename, "w") {} }
24
+ it {
25
+ plus, minus = runner.find_diff
26
+ expect(minus).to eql(['post1'])
27
+ expect(plus).to eql(['post3'])
28
+ }
29
+ end
30
+
31
+ context '#create' do
32
+ before { Post.create(name: 'post1') }
33
+ before { runner.create(%w[post1 post2]) }
34
+ it {
35
+ expect(Post.find_by(name: 'post1').body).not_to be_nil
36
+ expect(Post.find_by(name: 'post2').body).to be_nil
37
+ }
38
+ end
39
+
40
+ context '#delete' do
41
+ before {
42
+ post1 = Post.create(name: 'post1')
43
+ post2 = Post.create(name: 'post2')
44
+ runner.delete(%w[post1])
45
+ }
46
+ it {
47
+ expect(Post.find_by(name: 'post1')).to be_nil
48
+ expect(Post.find_by(name: 'post2')).not_to be_nil
49
+ }
50
+ end
51
+
52
+ context '#run' do
53
+ before { Post.new(name: 'post1').save_without_file }
54
+ before { Post.create(name: 'post2') }
55
+ before { File.open(Post.new(name: 'post3').filename, "w") {} }
56
+ it {
57
+ runner.run
58
+ expect(Post.find_by(name: 'post1')).to be_nil
59
+ expect(Post.find_by(name: 'post2')).not_to be_nil
60
+ expect(Post.find_by(name: 'post3')).not_to be_nil
61
+ }
62
+ end
63
+ end
64
+ else
65
+ describe 'SyncRunner' do
66
+ context '#run' do
67
+ let(:subject) { FluentdServer::SyncRunner.new.run }
68
+ it { should be_nil }
69
+ end
70
+ context '#find_locals' do
71
+ before { Post.create(name: 'post1') }
72
+ before { Post.create(name: 'post2') }
73
+ let(:subject) { FluentdServer::SyncRunner.new.find_locals }
74
+ it { should == [] }
75
+ end
76
+ end
77
+ end
@@ -4,11 +4,11 @@ require 'fluentd_server/model'
4
4
 
5
5
  describe 'TaskRunner' do
6
6
  let(:task) { Task.create }
7
- before { task.stub(:delay).and_return { task } }
7
+ before { allow(task).to receive(:delay).and_return(task) }
8
8
  after { Task.delete_all }
9
9
 
10
10
  context '.serf_path' do
11
- it { expect(File.executable?(Task.serf_path)).to be_true }
11
+ it { expect(File.executable?(Task.serf_path)).to be_truthy }
12
12
  end
13
13
 
14
14
  # ToDo: Test whether the serf command is executed correctly
@@ -20,7 +20,7 @@ describe 'TaskRunner' do
20
20
  it { expect { task.status }.not_to raise_error }
21
21
  end
22
22
 
23
- context '#configrest' do
23
+ context '#configtest' do
24
24
  it { expect { task.configtest }.not_to raise_error }
25
25
  end
26
26
  end
data/spec/web_spec.rb CHANGED
@@ -12,7 +12,7 @@ describe 'Post' do
12
12
  context 'get ALL posts' do
13
13
  it 'visit' do
14
14
  visit '/'
15
- page.status_code.should == 200
15
+ expect(page.status_code).to be == 200
16
16
  end
17
17
  end
18
18
 
@@ -20,7 +20,7 @@ describe 'Post' do
20
20
  before { visit '/posts/create' }
21
21
 
22
22
  it 'visit' do
23
- page.status_code.should == 200
23
+ expect(page.status_code).to be == 200
24
24
  end
25
25
 
26
26
  it 'create' do
@@ -38,7 +38,7 @@ describe 'Post' do
38
38
  before { visit "/posts/#{post.id}/edit" }
39
39
 
40
40
  it 'visit' do
41
- page.status_code.should == 200
41
+ expect(page.status_code).to be == 200
42
42
  end
43
43
 
44
44
  it 'edit' do
@@ -81,7 +81,7 @@ describe 'Task' do
81
81
  context 'list tasks' do
82
82
  it 'visit' do
83
83
  visit '/tasks'
84
- page.status_code.should == 200
84
+ expect(page.status_code).to be == 200
85
85
  end
86
86
  end
87
87
 
@@ -89,7 +89,7 @@ describe 'Task' do
89
89
  before { @task = Task.create }
90
90
  it 'visit' do
91
91
  visit "/tasks/#{@task.id}"
92
- page.status_code.should == 200
92
+ expect(page.status_code).to be == 200
93
93
  end
94
94
  end
95
95
 
data/views/_js.slim CHANGED
@@ -28,3 +28,9 @@ javascript:
28
28
  form.submit();
29
29
  return false;
30
30
  });
31
+ - if FluentdServer::Config.local_storage
32
+ javascript:
33
+ $('#post_name').attr("disabled", "disabled");
34
+ $('#post_body').attr("disabled", "disabled");
35
+ $('#post_submit').addClass('disabled');
36
+ $('#post_delete').addClass('disabled');
@@ -2,7 +2,7 @@ h2[style="margin-top:0px;"]
2
2
  | Create Config
3
3
  br
4
4
  == bootstrap_flash
5
- form[action=url_for("/posts") method="post" role="form"]
5
+ form[id="post_form" action=url_for("/posts") method="post" role="form"]
6
6
  .form-group
7
7
  label[for="post_name"]
8
8
  | Name:
@@ -15,6 +15,6 @@ form[action=url_for("/posts") method="post" role="form"]
15
15
  textarea#post_body.form-control[name="post[body]" rows="10"]
16
16
  = @post.body
17
17
  br
18
- button.btn.btn-success[type="submit"]
18
+ button.btn.btn-success[id="post_submit" type="submit"]
19
19
  | Submit
20
20
  br
@@ -2,7 +2,7 @@ h2[style="margin-top:0px;"]
2
2
  | Edit Config
3
3
  br
4
4
  == bootstrap_flash
5
- form action=url_for("/posts/#{@post.id}") method="post"
5
+ form id="post_form" action=url_for("/posts/#{@post.id}") method="post"
6
6
  .form-group
7
7
  label[for="post_name"]
8
8
  | Name:
@@ -17,8 +17,8 @@ form action=url_for("/posts/#{@post.id}") method="post"
17
17
  br
18
18
  a href=url_for("/api/#{@post.name}")
19
19
  | Render
20
- button.btn.btn-success[type="submit"]
20
+ button.btn.btn-success[id="post_submit" type="submit"]
21
21
  | Submit
22
22
  | &nbsp;
23
- a.btn.btn-danger data-method="post" data-confirm="true" href=url_for("/posts/#{@post.id}/delete")
23
+ a.btn.btn-danger id="post_delete" data-method="post" data-confirm="true" href=url_for("/posts/#{@post.id}/delete")
24
24
  | Delete
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluentd-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-26 00:00:00.000000000 Z
11
+ date: 2014-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: capybara
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -367,6 +367,8 @@ files:
367
367
  - lib/fluentd_server/environment.rb
368
368
  - lib/fluentd_server/logger.rb
369
369
  - lib/fluentd_server/model.rb
370
+ - lib/fluentd_server/sync_runner.rb
371
+ - lib/fluentd_server/sync_worker.rb
370
372
  - lib/fluentd_server/task_runner.rb
371
373
  - lib/fluentd_server/version.rb
372
374
  - lib/fluentd_server/web.rb
@@ -385,6 +387,7 @@ files:
385
387
  - spec/bench/result.md
386
388
  - spec/model_spec.rb
387
389
  - spec/spec_helper.rb
390
+ - spec/sync_runner_spec.rb
388
391
  - spec/task_runner_spec.rb
389
392
  - spec/tmp/.gitkeep
390
393
  - spec/web_helper_spec.rb
@@ -428,6 +431,7 @@ test_files:
428
431
  - spec/bench/result.md
429
432
  - spec/model_spec.rb
430
433
  - spec/spec_helper.rb
434
+ - spec/sync_runner_spec.rb
431
435
  - spec/task_runner_spec.rb
432
436
  - spec/tmp/.gitkeep
433
437
  - spec/web_helper_spec.rb