fluentd-server 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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