fluentd 1.11.5-x64-mingw32 → 1.12.4-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/.github/workflows/linux-test.yaml +36 -0
  6. data/.github/workflows/macos-test.yaml +30 -0
  7. data/.github/workflows/stale-actions.yml +22 -0
  8. data/.github/workflows/windows-test.yaml +35 -0
  9. data/.gitlab-ci.yml +41 -19
  10. data/CHANGELOG.md +158 -0
  11. data/MAINTAINERS.md +5 -2
  12. data/README.md +7 -4
  13. data/bin/fluent-cap-ctl +7 -0
  14. data/bin/fluent-ctl +7 -0
  15. data/fluentd.gemspec +6 -4
  16. data/lib/fluent/capability.rb +87 -0
  17. data/lib/fluent/command/bundler_injection.rb +1 -1
  18. data/lib/fluent/command/ca_generate.rb +6 -3
  19. data/lib/fluent/command/cap_ctl.rb +174 -0
  20. data/lib/fluent/command/cat.rb +0 -1
  21. data/lib/fluent/command/ctl.rb +177 -0
  22. data/lib/fluent/command/fluentd.rb +4 -0
  23. data/lib/fluent/command/plugin_config_formatter.rb +18 -2
  24. data/lib/fluent/command/plugin_generator.rb +31 -1
  25. data/lib/fluent/compat/parser.rb +2 -2
  26. data/lib/fluent/config/section.rb +2 -2
  27. data/lib/fluent/config/types.rb +2 -2
  28. data/lib/fluent/env.rb +4 -0
  29. data/lib/fluent/event.rb +3 -13
  30. data/lib/fluent/load.rb +0 -1
  31. data/lib/fluent/plugin.rb +5 -0
  32. data/lib/fluent/plugin/buffer.rb +2 -21
  33. data/lib/fluent/plugin/file_wrapper.rb +39 -3
  34. data/lib/fluent/plugin/formatter.rb +2 -2
  35. data/lib/fluent/plugin/formatter_csv.rb +1 -1
  36. data/lib/fluent/plugin/formatter_hash.rb +1 -1
  37. data/lib/fluent/plugin/formatter_ltsv.rb +5 -5
  38. data/lib/fluent/plugin/formatter_out_file.rb +3 -3
  39. data/lib/fluent/plugin/formatter_single_value.rb +2 -2
  40. data/lib/fluent/plugin/formatter_tsv.rb +2 -2
  41. data/lib/fluent/plugin/in_http.rb +24 -3
  42. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  43. data/lib/fluent/plugin/in_tail.rb +129 -41
  44. data/lib/fluent/plugin/in_tail/position_file.rb +53 -14
  45. data/lib/fluent/plugin/in_tcp.rb +1 -0
  46. data/lib/fluent/plugin/out_copy.rb +18 -5
  47. data/lib/fluent/plugin/out_exec_filter.rb +3 -3
  48. data/lib/fluent/plugin/out_forward.rb +61 -28
  49. data/lib/fluent/plugin/out_http.rb +9 -2
  50. data/lib/fluent/plugin/output.rb +18 -10
  51. data/lib/fluent/plugin/parser_csv.rb +2 -2
  52. data/lib/fluent/plugin/parser_syslog.rb +2 -2
  53. data/lib/fluent/plugin/storage_local.rb +4 -4
  54. data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
  55. data/lib/fluent/plugin_helper/inject.rb +4 -2
  56. data/lib/fluent/plugin_helper/retry_state.rb +4 -0
  57. data/lib/fluent/plugin_helper/server.rb +4 -2
  58. data/lib/fluent/plugin_helper/socket_option.rb +2 -2
  59. data/lib/fluent/supervisor.rb +153 -47
  60. data/lib/fluent/system_config.rb +2 -1
  61. data/lib/fluent/time.rb +58 -1
  62. data/lib/fluent/version.rb +1 -1
  63. data/lib/fluent/winsvc.rb +22 -4
  64. data/templates/new_gem/fluent-plugin.gemspec.erb +3 -3
  65. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  66. data/test/command/test_cap_ctl.rb +100 -0
  67. data/test/command/test_ctl.rb +57 -0
  68. data/test/command/test_fluentd.rb +38 -0
  69. data/test/command/test_plugin_config_formatter.rb +124 -2
  70. data/test/config/test_configurable.rb +1 -1
  71. data/test/plugin/in_tail/test_position_file.rb +100 -26
  72. data/test/plugin/test_file_wrapper.rb +105 -0
  73. data/test/plugin/test_in_exec.rb +1 -1
  74. data/test/plugin/test_in_http.rb +25 -0
  75. data/test/plugin/test_in_tail.rb +503 -42
  76. data/test/plugin/test_out_copy.rb +87 -0
  77. data/test/plugin/test_out_forward.rb +94 -6
  78. data/test/plugin/test_out_http.rb +20 -1
  79. data/test/plugin/test_output.rb +15 -3
  80. data/test/plugin/test_output_as_buffered_backup.rb +2 -0
  81. data/test/plugin/test_parser_csv.rb +14 -0
  82. data/test/plugin/test_parser_syslog.rb +16 -2
  83. data/test/plugin/test_sd_file.rb +1 -1
  84. data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
  85. data/test/plugin_helper/test_child_process.rb +5 -2
  86. data/test/plugin_helper/test_http_server_helper.rb +4 -2
  87. data/test/plugin_helper/test_inject.rb +29 -0
  88. data/test/plugin_helper/test_server.rb +26 -7
  89. data/test/test_capability.rb +74 -0
  90. data/test/test_event.rb +16 -0
  91. data/test/test_formatter.rb +30 -0
  92. data/test/test_output.rb +2 -2
  93. data/test/test_supervisor.rb +133 -10
  94. data/test/test_time_parser.rb +109 -0
  95. metadata +85 -31
  96. data/.travis.yml +0 -57
  97. data/appveyor.yml +0 -28
data/MAINTAINERS.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Fluentd Maintainers
2
2
 
3
3
  - [Naotoshi Seo](https://github.com/sonots), [ZOZO Technologies](https://tech.zozo.com/en/)
4
- - [Okkez](https://github.com/okkez), [Clearcode](https://www.clear-code.com/)
5
- - [Hiroshi Hatake](https://github.com/cosmo0920), [Clearcode](https://www.clear-code.com/)
4
+ - [Okkez](https://github.com/okkez)
5
+ - [Hiroshi Hatake](https://github.com/cosmo0920), [ClearCode](https://www.clear-code.com/)
6
6
  - [Masahiro Nakagawa](https://github.com/repeatedly), [Treasure Data](https://www.treasuredata.com/)
7
7
  - [Satoshi Tagomori](https://github.com/tagomoris), [Treasure Data](https://www.treasuredata.com/)
8
8
  - [Eduardo Silva](https://github.com/edsiper), [Arm Treasure Data](https://www.treasuredata.com/)
9
+ - [Fujimoto Seiji](https://github.com/fujimots), [ClearCode](https://www.clear-code.com/)
10
+ - [Takuro Ashie](https://github.com/ashie), [ClearCode](https://www.clear-code.com/)
11
+ - [Kentaro Hayashi](https://github.com/kenhys), [ClearCode](https://www.clear-code.com/)
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  Fluentd: Open-Source Log Collector
2
2
  ===================================
3
- Travis CI:
3
+ GitHub Actions:
4
4
 
5
- [<img src="https://travis-ci.org/fluent/fluentd.svg" />](https://travis-ci.org/fluent/fluentd) [![Code Climate](https://codeclimate.com/github/fluent/fluentd/badges/gpa.svg)](https://codeclimate.com/github/fluent/fluentd)
5
+ [![Testing on Ubuntu](https://github.com/fluent/fluentd/actions/workflows/linux-test.yaml/badge.svg?branch=master)](https://github.com/fluent/fluentd/actions/workflows/linux-test.yaml)
6
+ [![Testing on Windows](https://github.com/fluent/fluentd/actions/workflows/windows-test.yaml/badge.svg?branch=master)](https://github.com/fluent/fluentd/actions/workflows/windows-test.yaml)
7
+ [![Testing on macOS](https://github.com/fluent/fluentd/actions/workflows/macos-test.yaml/badge.svg?branch=master)](https://github.com/fluent/fluentd/actions/workflows/macos-test.yaml)
8
+ [![Code Climate](https://codeclimate.com/github/fluent/fluentd/badges/gpa.svg)](https://codeclimate.com/github/fluent/fluentd)
6
9
  [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1189/badge)](https://bestpractices.coreinfrastructure.org/projects/1189)
7
10
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Ffluent%2Ffluentd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Ffluent%2Ffluentd?ref=badge_shield)
8
11
 
@@ -13,7 +16,7 @@ Drone CI for Arm64:
13
16
  [Fluentd](https://www.fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](https://www.fluentd.org/blog/unified-logging-layer)).
14
17
 
15
18
  <p align="center">
16
- <img src="https://raw.githubusercontent.com/fluent/fluentd-docs-gitbook/1.0/images/fluentd-architecture.png" width="500px"/>
19
+ <img src="https://www.fluentd.org/images/fluentd-architecture.png" width="500px"/>
17
20
  </p>
18
21
 
19
22
  An event consists of *tag*, *time* and *record*. Tag is a string separated with '.' (e.g. myapp.access). It is used to categorize events. Time is a UNIX time recorded at occurrence of an event. Record is a JSON object.
@@ -78,7 +81,7 @@ You can run specified test via `TEST` environment variable:
78
81
  - Slack / Community: https://slack.fluentd.org
79
82
  - Newsletters: https://www.fluentd.org/newsletter
80
83
  - Author: [Sadayuki Furuhashi](https://github.com/frsyuki)
81
- - Copyright: 2011-2019 Fluentd Authors
84
+ - Copyright: 2011-2021 Fluentd Authors
82
85
  - License: Apache License, Version 2.0
83
86
 
84
87
  ## Security
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ here = File.dirname(__FILE__)
4
+ $LOAD_PATH << File.expand_path(File.join(here, '..', 'lib'))
5
+ require 'fluent/command/cap_ctl'
6
+
7
+ Fluent::CapCtl.new.call
data/bin/fluent-ctl ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ here = File.dirname(__FILE__)
4
+ $LOAD_PATH << File.expand_path(File.join(here, '..', 'lib'))
5
+ require 'fluent/command/ctl'
6
+
7
+ Fluent::Ctl.new.call
data/fluentd.gemspec CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.required_ruby_version = '>= 2.4'
20
20
 
21
+ gem.add_runtime_dependency("bundler")
21
22
  gem.add_runtime_dependency("msgpack", [">= 1.3.1", "< 2.0.0"])
22
23
  gem.add_runtime_dependency("yajl-ruby", ["~> 1.0"])
23
24
  gem.add_runtime_dependency("cool.io", [">= 1.4.5", "< 2.0.0"])
@@ -27,12 +28,14 @@ Gem::Specification.new do |gem|
27
28
  gem.add_runtime_dependency("tzinfo", [">= 1.0", "< 3.0"])
28
29
  gem.add_runtime_dependency("tzinfo-data", ["~> 1.0"])
29
30
  gem.add_runtime_dependency("strptime", [">= 0.2.2", "< 1.0.0"])
31
+ gem.add_runtime_dependency("webrick", [">= 1.4.2", "< 1.8.0"])
30
32
 
31
33
  # build gem for a certain platform. see also Rakefile
32
34
  fake_platform = ENV['GEM_BUILD_FAKE_PLATFORM'].to_s
33
35
  gem.platform = fake_platform unless fake_platform.empty?
34
36
  if /mswin|mingw/ =~ fake_platform || (/mswin|mingw/ =~ RUBY_PLATFORM && fake_platform.empty?)
35
- gem.add_runtime_dependency("win32-service", ["~> 2.1.5"])
37
+ gem.add_runtime_dependency("win32-api", [">= 1.10", "< 2.0.0"])
38
+ gem.add_runtime_dependency("win32-service", ["~> 2.2.0"])
36
39
  gem.add_runtime_dependency("win32-ipc", ["~> 0.7.0"])
37
40
  gem.add_runtime_dependency("win32-event", ["~> 0.6.3"])
38
41
  gem.add_runtime_dependency("windows-pr", ["~> 1.2.6"])
@@ -43,11 +46,10 @@ Gem::Specification.new do |gem|
43
46
  gem.add_development_dependency("flexmock", ["~> 2.0"])
44
47
  gem.add_development_dependency("parallel_tests", ["~> 0.15.3"])
45
48
  gem.add_development_dependency("simplecov", ["~> 0.7"])
46
- gem.add_development_dependency("rr", ["~> 1.0"])
49
+ gem.add_development_dependency("rr", ["~> 3.0"])
47
50
  gem.add_development_dependency("timecop", ["~> 0.9"])
48
51
  gem.add_development_dependency("test-unit", ["~> 3.3"])
49
52
  gem.add_development_dependency("test-unit-rr", ["~> 1.0"])
50
53
  gem.add_development_dependency("oj", [">= 2.14", "< 4"])
51
- gem.add_development_dependency("ext_monitor", [">= 0.1.2", "< 0.2"])
52
- gem.add_development_dependency("async-http")
54
+ gem.add_development_dependency("async-http", ">= 0.50.0")
53
55
  end
@@ -0,0 +1,87 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require "fluent/env"
18
+
19
+ if Fluent.linux?
20
+ begin
21
+ require 'capng'
22
+ rescue LoadError
23
+ end
24
+ end
25
+
26
+ module Fluent
27
+ if defined?(CapNG)
28
+ class Capability
29
+ def initialize(target = nil, pid = nil)
30
+ @capng = CapNG.new(target, pid)
31
+ end
32
+
33
+ def usable?
34
+ true
35
+ end
36
+
37
+ def apply(select_set)
38
+ @capng.apply(select_set)
39
+ end
40
+
41
+ def clear(select_set)
42
+ @capng.clear(select_set)
43
+ end
44
+
45
+ def have_capability?(type, capability)
46
+ @capng.have_capability?(type, capability)
47
+ end
48
+
49
+ def update(action, type, capability_or_capability_array)
50
+ @capng.update(action, type, capability_or_capability_array)
51
+ end
52
+
53
+ def have_capabilities?(select_set)
54
+ @capng.have_capabilities?(select_set)
55
+ end
56
+ end
57
+ else
58
+ class Capability
59
+ def initialize(target = nil, pid = nil)
60
+ end
61
+
62
+ def usable?
63
+ false
64
+ end
65
+
66
+ def apply(select_set)
67
+ false
68
+ end
69
+
70
+ def clear(select_set)
71
+ false
72
+ end
73
+
74
+ def have_capability?(type, capability)
75
+ false
76
+ end
77
+
78
+ def update(action, type, capability_or_capability_array)
79
+ false
80
+ end
81
+
82
+ def have_capabilities?(select_set)
83
+ false
84
+ end
85
+ end
86
+ end
87
+ end
@@ -40,6 +40,6 @@ else
40
40
  File.expand_path(File.join(File.dirname(__FILE__), 'fluentd.rb')),
41
41
  ] + ARGV
42
42
 
43
- exec *cmdline
43
+ exec(*cmdline)
44
44
  exit! 127
45
45
  end
@@ -75,6 +75,8 @@ HELP
75
75
 
76
76
  digest = OpenSSL::Digest::SHA256.new
77
77
 
78
+ factory = OpenSSL::X509::ExtensionFactory.new
79
+
78
80
  cert = OpenSSL::X509::Certificate.new
79
81
  cert.not_before = Time.at(0)
80
82
  cert.not_after = Time.now + 5 * 365 * 86400 # 5 years after
@@ -82,7 +84,7 @@ HELP
82
84
  cert.serial = 1
83
85
  cert.issuer = issuer
84
86
  cert.subject = subject
85
- cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)]))
87
+ cert.add_extension(factory.create_extension('basicConstraints', 'CA:TRUE'))
86
88
  cert.sign(key, digest)
87
89
 
88
90
  return cert, key
@@ -111,8 +113,9 @@ HELP
111
113
  cert.issuer = issuer
112
114
  cert.subject = subject
113
115
 
114
- cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
115
- cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
116
+ factory = OpenSSL::X509::ExtensionFactory.new
117
+ server_cert.add_extension(factory.create_extension('basicConstraints', 'CA:FALSE'))
118
+ server_cert.add_extension(factory.create_extension('nsCertType', 'server'))
116
119
 
117
120
  cert.sign ca_key, digest
118
121
 
@@ -0,0 +1,174 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'optparse'
18
+ require 'fluent/log'
19
+ require 'fluent/env'
20
+ require 'fluent/capability'
21
+
22
+ module Fluent
23
+ class CapCtl
24
+ def prepare_option_parser
25
+ @op = OptionParser.new
26
+
27
+ @op.on('--clear', "Clear Fluentd Ruby capability") {|s|
28
+ @opts[:clear_capabilities] = true
29
+ }
30
+
31
+ @op.on('--add [CAPABILITITY1,CAPABILITY2, ...]', "Add capabilities into Fluentd Ruby") {|s|
32
+ @opts[:add_capabilities] = s
33
+ }
34
+
35
+ @op.on('--drop [CAPABILITITY1,CAPABILITY2, ...]', "Drop capabilities from Fluentd Ruby") {|s|
36
+ @opts[:drop_capabilities] = s
37
+ }
38
+
39
+ @op.on('--get', "Get capabilities for Fluentd Ruby") {|s|
40
+ @opts[:get_capabilities] = true
41
+ }
42
+
43
+ @op.on('-f', '--file FILE', "Specify target file to add Linux capabilities") {|s|
44
+ @opts[:target_file] = s
45
+ }
46
+ end
47
+
48
+ def usage(msg)
49
+ puts @op.to_s
50
+ puts "error: #{msg}" if msg
51
+ exit 1
52
+ end
53
+
54
+ def initialize(argv = ARGV)
55
+ @opts = {}
56
+ @argv = argv
57
+
58
+ if Fluent.linux?
59
+ begin
60
+ require 'capng'
61
+
62
+ @capng = CapNG.new
63
+ rescue LoadError
64
+ puts "Error: capng_c is not loaded. Please install it first."
65
+ exit 1
66
+ end
67
+ else
68
+ puts "Error: This environment is not supported."
69
+ exit 2
70
+ end
71
+
72
+ prepare_option_parser
73
+ end
74
+
75
+ def call
76
+ parse_options!(@argv)
77
+
78
+ target_file = if !!@opts[:target_file]
79
+ @opts[:target_file]
80
+ else
81
+ File.readlink("/proc/self/exe")
82
+ end
83
+
84
+ if @opts[:clear_capabilities]
85
+ clear_capabilities(@opts, target_file)
86
+ elsif @opts[:add_capabilities]
87
+ add_capabilities(@opts, target_file)
88
+ elsif @opts[:drop_capabilities]
89
+ drop_capabilities(@opts, target_file)
90
+ end
91
+ if @opts[:get_capabilities]
92
+ get_capabilities(@opts, target_file)
93
+ end
94
+ end
95
+
96
+ def clear_capabilities(opts, target_file)
97
+ if !!opts[:clear_capabilities]
98
+ @capng.clear(:caps)
99
+ ret = @capng.apply_caps_file(target_file)
100
+ puts "Clear capabilities #{ret ? 'done' : 'fail'}."
101
+ end
102
+ end
103
+
104
+ def add_capabilities(opts, target_file)
105
+ if add_caps = opts[:add_capabilities]
106
+ @capng.clear(:caps)
107
+ @capng.caps_file(target_file)
108
+ capabilities = add_caps.split(/\s*,\s*/)
109
+ check_capabilities(capabilities, get_valid_capabilities)
110
+ ret = @capng.update(:add,
111
+ CapNG::Type::EFFECTIVE | CapNG::Type::INHERITABLE | CapNG::Type::PERMITTED,
112
+ capabilities)
113
+ puts "Updating #{add_caps} #{ret ? 'done' : 'fail'}."
114
+ ret = @capng.apply_caps_file(target_file)
115
+ puts "Adding #{add_caps} #{ret ? 'done' : 'fail'}."
116
+ end
117
+ end
118
+
119
+ def drop_capabilities(opts, target_file)
120
+ if drop_caps = opts[:drop_capabilities]
121
+ @capng.clear(:caps)
122
+ @capng.caps_file(target_file)
123
+ capabilities = drop_caps.split(/\s*,\s*/)
124
+ check_capabilities(capabilities, get_valid_capabilities)
125
+ ret = @capng.update(:drop,
126
+ CapNG::Type::EFFECTIVE | CapNG::Type::INHERITABLE | CapNG::Type::PERMITTED,
127
+ capabilities)
128
+ puts "Updating #{drop_caps} #{ret ? 'done' : 'fail'}."
129
+ @capng.apply_caps_file(target_file)
130
+ puts "Dropping #{drop_caps} #{ret ? 'done' : 'fail'}."
131
+ end
132
+ end
133
+
134
+ def get_capabilities(opts, target_file)
135
+ if opts[:get_capabilities]
136
+ @capng.caps_file(target_file)
137
+ print = CapNG::Print.new
138
+ puts "Capabilities in '#{target_file}',"
139
+ puts "Effective: #{print.caps_text(:buffer, :effective)}"
140
+ puts "Inheritable: #{print.caps_text(:buffer, :inheritable)}"
141
+ puts "Permitted: #{print.caps_text(:buffer, :permitted)}"
142
+ end
143
+ end
144
+
145
+ def get_valid_capabilities
146
+ capabilities = []
147
+ cap = CapNG::Capability.new
148
+ cap.each do |_code, capability|
149
+ capabilities << capability
150
+ end
151
+ capabilities
152
+ end
153
+
154
+ def check_capabilities(capabilities, valid_capabilities)
155
+ capabilities.each do |capability|
156
+ unless valid_capabilities.include?(capability)
157
+ raise ArgumentError, "'#{capability}' is not valid capability. Valid Capabilities are: #{valid_capabilities.join(", ")}"
158
+ end
159
+ end
160
+ end
161
+
162
+ def parse_options!(argv)
163
+ begin
164
+ rest = @op.parse(argv)
165
+
166
+ if rest.length != 0
167
+ usage nil
168
+ end
169
+ rescue
170
+ usage $!.to_s
171
+ end
172
+ end
173
+ end
174
+ end
@@ -101,7 +101,6 @@ rescue
101
101
  usage $!.to_s
102
102
  end
103
103
 
104
- require 'thread'
105
104
  require 'socket'
106
105
  require 'yajl'
107
106
  require 'msgpack'
@@ -0,0 +1,177 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'optparse'
18
+ require 'fluent/env'
19
+ require 'fluent/version'
20
+ if Fluent.windows?
21
+ require 'win32/event'
22
+ require 'win32/service'
23
+ end
24
+
25
+ module Fluent
26
+ class Ctl
27
+ DEFAULT_OPTIONS = {}
28
+
29
+ if Fluent.windows?
30
+ include Windows::ServiceConstants
31
+ include Windows::ServiceStructs
32
+ include Windows::ServiceFunctions
33
+
34
+ COMMAND_MAP = {
35
+ shutdown: "",
36
+ restart: "HUP",
37
+ flush: "USR1",
38
+ reload: "USR2",
39
+ }
40
+ WINSVC_CONTROL_CODE_MAP = {
41
+ shutdown: SERVICE_CONTROL_STOP,
42
+ # 128 - 255: user-defined control code
43
+ # See https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-controlservice
44
+ restart: 128,
45
+ flush: 129,
46
+ reload: SERVICE_CONTROL_PARAMCHANGE,
47
+ }
48
+ else
49
+ COMMAND_MAP = {
50
+ shutdown: :TERM,
51
+ restart: :HUP,
52
+ flush: :USR1,
53
+ reload: :USR2,
54
+ }
55
+ end
56
+
57
+ def initialize(argv = ARGV)
58
+ @argv = argv
59
+ @options = {}
60
+ @opt_parser = OptionParser.new
61
+ configure_option_parser
62
+ @options.merge!(DEFAULT_OPTIONS)
63
+ parse_options!
64
+ end
65
+
66
+ def help_text
67
+ text = "\n"
68
+ if Fluent.windows?
69
+ text << "Usage: #{$PROGRAM_NAME} COMMAND [PID_OR_SVCNAME]\n"
70
+ else
71
+ text << "Usage: #{$PROGRAM_NAME} COMMAND PID\n"
72
+ end
73
+ text << "\n"
74
+ text << "Commands: \n"
75
+ COMMAND_MAP.each do |key, value|
76
+ text << " #{key}\n"
77
+ end
78
+ text
79
+ end
80
+
81
+ def usage(msg = nil)
82
+ puts help_text
83
+ if msg
84
+ puts
85
+ puts "Error: #{msg}"
86
+ end
87
+ exit 1
88
+ end
89
+
90
+ def call
91
+ if Fluent.windows?
92
+ if @pid_or_svcname =~ /^[0-9]+$/
93
+ # Use as PID
94
+ return call_windows_event(@command, "fluentd_#{@pid_or_svcname}")
95
+ end
96
+
97
+ unless call_winsvc_control_code(@command, @pid_or_svcname)
98
+ puts "Cannot send control code to #{@pid_or_svcname} service, try to send an event with this name ..."
99
+ call_windows_event(@command, @pid_or_svcname)
100
+ end
101
+ else
102
+ call_signal(@command, @pid_or_svcname)
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def call_signal(command, pid)
109
+ signal = COMMAND_MAP[command.to_sym]
110
+ Process.kill(signal, pid.to_i)
111
+ end
112
+
113
+ def call_winsvc_control_code(command, pid_or_svcname)
114
+ status = SERVICE_STATUS.new
115
+
116
+ begin
117
+ handle_scm = OpenSCManager(nil, nil, SC_MANAGER_CONNECT)
118
+ FFI.raise_windows_error('OpenSCManager') if handle_scm == 0
119
+
120
+ handle_scs = OpenService(handle_scm, "fluentdwinsvc", SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL)
121
+ FFI.raise_windows_error('OpenService') if handle_scs == 0
122
+
123
+ control_code = WINSVC_CONTROL_CODE_MAP[command.to_sym]
124
+
125
+ unless ControlService(handle_scs, control_code, status)
126
+ FFI.raise_windows_error('ControlService')
127
+ end
128
+ rescue => e
129
+ puts e
130
+ state = status[:dwCurrentState]
131
+ return state == SERVICE_STOPPED || state == SERVICE_STOP_PENDING
132
+ ensure
133
+ CloseServiceHandle(handle_scs)
134
+ CloseServiceHandle(handle_scm)
135
+ end
136
+
137
+ return true
138
+ end
139
+
140
+ def call_windows_event(command, pid_or_svcname)
141
+ prefix = pid_or_svcname
142
+ event_name = COMMAND_MAP[command.to_sym]
143
+ suffix = event_name.empty? ? "" : "_#{event_name}"
144
+
145
+ begin
146
+ event = Win32::Event.open("#{prefix}#{suffix}")
147
+ event.set
148
+ event.close
149
+ rescue Errno::ENOENT => e
150
+ puts "Error: Cannot find the fluentd process with the event name: \"#{prefix}\""
151
+ end
152
+ end
153
+
154
+ def configure_option_parser
155
+ @opt_parser.banner = help_text
156
+ @opt_parser.version = Fluent::VERSION
157
+ end
158
+
159
+ def parse_options!
160
+ @opt_parser.parse!(@argv)
161
+
162
+ @command = @argv[0]
163
+ @pid_or_svcname = @argv[1] || "fluentdwinsvc"
164
+
165
+ usage("Command isn't specified!") if @command.nil? || @command.empty?
166
+ usage("Unknown command: #{@command}") unless COMMAND_MAP.has_key?(@command.to_sym)
167
+
168
+ if Fluent.windows?
169
+ usage("PID or SVCNAME isn't specified!") if @pid_or_svcname.nil? || @pid_or_svcname.empty?
170
+ else
171
+ usage("PID isn't specified!") if @pid_or_svcname.nil? || @pid_or_svcname.empty?
172
+ usage("Invalid PID: #{pid}") unless @pid_or_svcname =~ /^[0-9]+$/
173
+ end
174
+ end
175
+ end
176
+ end
177
+