fluent-plugin-google-cloud 0.6.24 → 0.6.25.pre.1

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: e9d4e0c7112b19f2fdf43ac7bad7c2d030932f63
4
- data.tar.gz: ea83fcd3888666a51aae9c4a03ea0ffb0bdba527
3
+ metadata.gz: ae6de5c365ece78d5541faf3c03e1ebbd7dd218a
4
+ data.tar.gz: 8236d705f453819f152eb08130c0c1bdfb452080
5
5
  SHA512:
6
- metadata.gz: 2b179f5f31c11216c3e04b5d071cb244700f8352ed11fe1fa00fcf3282e5016e52a02e1880859d92a445d641e9bc1280a861a19896e5166ee493ad9b81569b2a
7
- data.tar.gz: 3e9e799eb94b3e35156ce44cb8511f942082ac2ebc6bde9d21590543b421148f029f24f499c5373c7ca60a57054e066bbce3c9b19e8c312fa562f902420edf1d
6
+ metadata.gz: '0695b58ed5d1b52cde93dad05374fb761e56ec0163594d6987ccd6d67c47a517009a4363032c634f36a1c946cbbf0534c1a662b019d24d81777ff95f2fe7a730'
7
+ data.tar.gz: f63241976bed1b8bcda026de9e20fff9d91347879a9fded573f5b24e58676fe8d2e84c8d1f823b9d40b8a412fdb421dde184b322145e27fafadbc5e5ab89c765
@@ -0,0 +1,159 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-google-cloud (0.6.25.pre.1)
5
+ fluentd (~> 0.10)
6
+ google-api-client (~> 0.17)
7
+ google-cloud-logging (~> 1.3, >= 1.3.2)
8
+ google-protobuf (~> 3.6, >= 3.6.1)
9
+ googleapis-common-protos (~> 1.3)
10
+ googleauth (~> 0.6)
11
+ grpc (~> 1.0)
12
+ json (~> 2.1)
13
+
14
+ GEM
15
+ remote: https://rubygems.org/
16
+ specs:
17
+ addressable (2.5.2)
18
+ public_suffix (>= 2.0.2, < 4.0)
19
+ ast (2.4.0)
20
+ cool.io (1.5.3)
21
+ crack (0.4.3)
22
+ safe_yaml (~> 1.0.0)
23
+ declarative (0.0.10)
24
+ declarative-option (0.1.0)
25
+ faraday (0.15.2)
26
+ multipart-post (>= 1.2, < 3)
27
+ fluentd (0.14.25)
28
+ cool.io (>= 1.4.5, < 2.0.0)
29
+ http_parser.rb (>= 0.5.1, < 0.7.0)
30
+ msgpack (>= 0.7.0, < 2.0.0)
31
+ ruby_dig (~> 0.0.2)
32
+ serverengine (>= 2.0.4, < 3.0.0)
33
+ sigdump (~> 0.2.2)
34
+ strptime (~> 0.1.7)
35
+ tzinfo (~> 1.0)
36
+ tzinfo-data (~> 1.0)
37
+ yajl-ruby (~> 1.0)
38
+ google-api-client (0.23.9)
39
+ addressable (~> 2.5, >= 2.5.1)
40
+ googleauth (>= 0.5, < 0.7.0)
41
+ httpclient (>= 2.8.1, < 3.0)
42
+ mime-types (~> 3.0)
43
+ representable (~> 3.0)
44
+ retriable (>= 2.0, < 4.0)
45
+ signet (~> 0.9)
46
+ google-cloud-core (1.2.6)
47
+ google-cloud-env (~> 1.0)
48
+ google-cloud-env (1.0.4)
49
+ faraday (~> 0.11)
50
+ google-cloud-logging (1.5.4)
51
+ google-cloud-core (~> 1.2)
52
+ google-gax (~> 1.3)
53
+ googleapis-common-protos-types (>= 1.0.2)
54
+ stackdriver-core (~> 1.3)
55
+ google-gax (1.3.0)
56
+ google-protobuf (~> 3.2)
57
+ googleapis-common-protos (>= 1.3.5, < 2.0)
58
+ googleauth (~> 0.6.2)
59
+ grpc (>= 1.7.2, < 2.0)
60
+ rly (~> 0.2.3)
61
+ google-protobuf (3.6.1)
62
+ googleapis-common-protos (1.3.7)
63
+ google-protobuf (~> 3.0)
64
+ googleapis-common-protos-types (~> 1.0)
65
+ grpc (~> 1.0)
66
+ googleapis-common-protos-types (1.0.2)
67
+ google-protobuf (~> 3.0)
68
+ googleauth (0.6.6)
69
+ faraday (~> 0.12)
70
+ jwt (>= 1.4, < 3.0)
71
+ memoist (~> 0.12)
72
+ multi_json (~> 1.11)
73
+ os (>= 0.9, < 2.0)
74
+ signet (~> 0.7)
75
+ grpc (1.15.0)
76
+ google-protobuf (~> 3.1)
77
+ googleapis-common-protos-types (~> 1.0.0)
78
+ hashdiff (0.3.7)
79
+ http_parser.rb (0.6.0)
80
+ httpclient (2.8.3)
81
+ json (2.1.0)
82
+ jwt (2.1.0)
83
+ memoist (0.16.0)
84
+ metaclass (0.0.4)
85
+ mime-types (3.2.2)
86
+ mime-types-data (~> 3.2015)
87
+ mime-types-data (3.2018.0812)
88
+ mocha (1.7.0)
89
+ metaclass (~> 0.0.1)
90
+ msgpack (1.2.4)
91
+ multi_json (1.13.1)
92
+ multipart-post (2.0.0)
93
+ os (1.0.0)
94
+ parser (2.5.1.2)
95
+ ast (~> 2.4.0)
96
+ power_assert (1.1.3)
97
+ powerpack (0.1.2)
98
+ prometheus-client (0.7.1)
99
+ quantile (~> 0.2.0)
100
+ public_suffix (3.0.3)
101
+ quantile (0.2.1)
102
+ rainbow (2.2.2)
103
+ rake
104
+ rake (10.5.0)
105
+ representable (3.0.4)
106
+ declarative (< 0.1.0)
107
+ declarative-option (< 0.2.0)
108
+ uber (< 0.2.0)
109
+ retriable (3.1.2)
110
+ rly (0.2.3)
111
+ rubocop (0.39.0)
112
+ parser (>= 2.3.0.7, < 3.0)
113
+ powerpack (~> 0.1)
114
+ rainbow (>= 1.99.1, < 3.0)
115
+ ruby-progressbar (~> 1.7)
116
+ unicode-display_width (~> 1.0, >= 1.0.1)
117
+ ruby-progressbar (1.10.0)
118
+ ruby_dig (0.0.2)
119
+ safe_yaml (1.0.4)
120
+ serverengine (2.0.7)
121
+ sigdump (~> 0.2.2)
122
+ sigdump (0.2.4)
123
+ signet (0.9.1)
124
+ addressable (~> 2.3)
125
+ faraday (~> 0.9)
126
+ jwt (>= 1.5, < 3.0)
127
+ multi_json (~> 1.10)
128
+ stackdriver-core (1.3.2)
129
+ google-cloud-core (~> 1.2)
130
+ strptime (0.1.9)
131
+ test-unit (3.2.8)
132
+ power_assert
133
+ thread_safe (0.3.6)
134
+ tzinfo (1.2.5)
135
+ thread_safe (~> 0.1)
136
+ tzinfo-data (1.2018.5)
137
+ tzinfo (>= 1.0.0)
138
+ uber (0.1.0)
139
+ unicode-display_width (1.4.0)
140
+ webmock (2.3.2)
141
+ addressable (>= 2.3.6)
142
+ crack (>= 0.3.2)
143
+ hashdiff
144
+ yajl-ruby (1.4.1)
145
+
146
+ PLATFORMS
147
+ ruby
148
+
149
+ DEPENDENCIES
150
+ fluent-plugin-google-cloud!
151
+ mocha (~> 1.1)
152
+ prometheus-client (~> 0.7.1)
153
+ rake (~> 10.3)
154
+ rubocop (~> 0.39.0)
155
+ test-unit (~> 3.0)
156
+ webmock (~> 2.3.1)
157
+
158
+ BUNDLED WITH
159
+ 1.16.4
@@ -10,7 +10,7 @@ eos
10
10
  gem.homepage =
11
11
  'https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud'
12
12
  gem.license = 'Apache-2.0'
13
- gem.version = '0.6.24'
13
+ gem.version = '0.6.25.pre.1'
14
14
  gem.authors = ['Stackdriver Agents Team']
15
15
  gem.email = ['stackdriver-agents@google.com']
16
16
  gem.required_ruby_version = Gem::Requirement.new('>= 2.2')
@@ -25,7 +25,7 @@ eos
25
25
  gem.add_runtime_dependency 'google-cloud-logging', '~> 1.3', '>= 1.3.2'
26
26
  gem.add_runtime_dependency 'googleauth', '~> 0.6'
27
27
  gem.add_runtime_dependency 'grpc', '~> 1.0'
28
- gem.add_runtime_dependency 'json', '~> 1.8'
28
+ gem.add_runtime_dependency 'json', '~> 2.1'
29
29
  gem.add_runtime_dependency 'google-protobuf', '~> 3.6', '>= 3.6.1'
30
30
 
31
31
  gem.add_development_dependency 'mocha', '~> 1.1'
@@ -100,4 +100,7 @@ module Fluent
100
100
  end
101
101
  end
102
102
  end
103
+
104
+ # For Fluentd v0.12 compatibility.
105
+ AddInsertIdsFilter = Fluent::Plugin::AddInsertIdsFilter
103
106
  end
@@ -86,7 +86,7 @@ module Fluent
86
86
  resource_type: 'container',
87
87
  extra_resource_labels: %w(namespace_id pod_id container_name),
88
88
  extra_common_labels: %w(namespace_name pod_name),
89
- metadata_attributes: %w(kube-env),
89
+ metadata_attributes: %w(cluster-name cluster-location),
90
90
  stream_severity_map: {
91
91
  'stdout' => 'INFO',
92
92
  'stderr' => 'ERROR'
@@ -550,10 +550,12 @@ module Fluent
550
550
  @write_request = method(:write_request_via_rest)
551
551
  end
552
552
 
553
- # Log an informational message containing the Logs viewer URL
554
- @log.info 'Logs viewer address: https://console.cloud.google.com/logs/',
555
- "viewer?project=#{@project_id}&resource=#{@resource.type}/",
556
- "instance_id/#{@vm_id}"
553
+ if [Platform::GCE, Platform::EC2].include?(@platform)
554
+ # Log an informational message containing the Logs viewer URL
555
+ @log.info 'Logs viewer address: https://console.cloud.google.com/logs/',
556
+ "viewer?project=#{@project_id}&resource=#{@resource.type}/",
557
+ "instance_id/#{@vm_id}"
558
+ end
557
559
  end
558
560
 
559
561
  def start
@@ -1027,8 +1029,10 @@ module Fluent
1027
1029
  # All metadata parameters must now be set.
1028
1030
  missing = []
1029
1031
  missing << 'project_id' unless @project_id
1030
- missing << 'zone' unless @zone
1031
- missing << 'vm_id' unless @vm_id
1032
+ if @platform != Platform::OTHER
1033
+ missing << 'zone' unless @zone
1034
+ missing << 'vm_id' unless @vm_id
1035
+ end
1032
1036
  return if missing.empty?
1033
1037
  raise Fluent::ConfigError,
1034
1038
  "Unable to obtain metadata parameters: #{missing.join(' ')}"
@@ -1144,12 +1148,11 @@ module Fluent
1144
1148
 
1145
1149
  # GKE container.
1146
1150
  when GKE_CONSTANTS[:resource_type]
1147
- raw_kube_env = fetch_gce_metadata('instance/attributes/kube-env')
1148
- kube_env = YAML.load(raw_kube_env)
1149
1151
  return {
1150
1152
  'instance_id' => @vm_id,
1151
1153
  'zone' => @zone,
1152
- 'cluster_name' => cluster_name_from_kube_env(kube_env)
1154
+ 'cluster_name' =>
1155
+ fetch_gce_metadata('instance/attributes/cluster-name')
1153
1156
  }
1154
1157
 
1155
1158
  # Cloud Dataproc.
@@ -1531,15 +1534,6 @@ module Fluent
1531
1534
  end
1532
1535
  end
1533
1536
 
1534
- def cluster_name_from_kube_env(kube_env)
1535
- return kube_env['CLUSTER_NAME'] if kube_env.key?('CLUSTER_NAME')
1536
- instance_prefix = kube_env['INSTANCE_PREFIX']
1537
- gke_name_match = /^gke-(.+)-[0-9a-f]{8}$/.match(instance_prefix)
1538
- return gke_name_match.captures[0] if gke_name_match &&
1539
- !gke_name_match.captures.empty?
1540
- instance_prefix
1541
- end
1542
-
1543
1537
  def time_or_nil(ts_secs, ts_nanos)
1544
1538
  Time.at((Integer ts_secs), (Integer ts_nanos) / 1_000.0)
1545
1539
  rescue ArgumentError, TypeError
@@ -81,26 +81,27 @@ module BaseTest
81
81
  assert_equal CUSTOM_VM_ID, d.instance.vm_id
82
82
  end
83
83
 
84
- def test_configure_invalid_metadata_missing_parts
84
+ def test_configure_metadata_missing_parts_on_other_platforms
85
85
  setup_no_metadata_service_stubs
86
86
  Fluent::GoogleCloudOutput::CredentialsInfo.stubs(:project_id).returns(nil)
87
- { CONFIG_MISSING_METADATA_PROJECT_ID => ['project_id'],
88
- CONFIG_MISSING_METADATA_ZONE => ['zone'],
89
- CONFIG_MISSING_METADATA_VM_ID => ['vm_id'],
90
- CONFIG_MISSING_METADATA_ALL => %w(project_id zone vm_id)
91
- }.each_with_index do |(config, parts), index|
92
- exception_count = 0
87
+ [[CONFIG_MISSING_METADATA_PROJECT_ID, ['project_id'], false],
88
+ [CONFIG_MISSING_METADATA_ZONE, [], true],
89
+ [CONFIG_MISSING_METADATA_VM_ID, [], true],
90
+ [CONFIG_MISSING_METADATA_ALL, ['project_id'], false]
91
+ ].each_with_index do |(config, missing_parts, is_valid_config), index|
93
92
  begin
94
93
  create_driver(config)
94
+ assert_true is_valid_config, "Invalid config at index #{index} should "\
95
+ 'have raised an error.'
95
96
  rescue Fluent::ConfigError => error
97
+ assert_false is_valid_config, "Valid config at index #{index} should "\
98
+ "not have raised an error #{error}."
96
99
  assert error.message.include?('Unable to obtain metadata parameters:'),
97
100
  "Index #{index} failed."
98
- parts.each do |part|
101
+ missing_parts.each do |part|
99
102
  assert error.message.include?(part), "Index #{index} failed."
100
103
  end
101
- exception_count += 1
102
104
  end
103
- assert_equal 1, exception_count, "Index #{index} failed."
104
105
  end
105
106
  end
106
107
 
@@ -179,7 +180,7 @@ module BaseTest
179
180
  setup_gce_metadata_stubs
180
181
  # This would cause the resource type to be container.googleapis.com if not
181
182
  # for the detect_subservice=false config.
182
- setup_container_metadata_stubs
183
+ setup_k8s_metadata_stubs
183
184
  d = create_driver(NO_DETECT_SUBSERVICE_CONFIG)
184
185
  d.run
185
186
  assert_equal COMPUTE_CONSTANTS[:resource_type], d.instance.resource.type
@@ -467,7 +468,7 @@ module BaseTest
467
468
 
468
469
  def test_structured_payload_json_log_default_container_not_parsed
469
470
  setup_gce_metadata_stubs
470
- setup_container_metadata_stubs
471
+ setup_k8s_metadata_stubs
471
472
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
472
473
  '"data": 5000, "some_null_field": null}'
473
474
  setup_logging_stubs do
@@ -484,7 +485,7 @@ module BaseTest
484
485
 
485
486
  def test_structured_payload_json_log_detect_json_container_not_parsed
486
487
  setup_gce_metadata_stubs
487
- setup_container_metadata_stubs
488
+ setup_k8s_metadata_stubs
488
489
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
489
490
  '"data": 5000, "some_null_field": null}'
490
491
  setup_logging_stubs do
@@ -499,7 +500,7 @@ module BaseTest
499
500
 
500
501
  def test_structured_payload_json_log_detect_json_container_parsed
501
502
  setup_gce_metadata_stubs
502
- setup_container_metadata_stubs
503
+ setup_k8s_metadata_stubs
503
504
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
504
505
  '"data": 5000, "some_null_field": null}'
505
506
  setup_logging_stubs do
@@ -538,7 +539,7 @@ module BaseTest
538
539
  # match, thus the original tag is used as the log name.
539
540
  def test_handle_empty_container_name
540
541
  setup_gce_metadata_stubs
541
- setup_container_metadata_stubs
542
+ setup_k8s_metadata_stubs
542
543
  container_name = ''
543
544
  # This tag will not match the kubernetes regex because it requires a
544
545
  # non-empty container name.
@@ -560,7 +561,7 @@ module BaseTest
560
561
  # 'require_valid_tags' is true.
561
562
  def test_reject_non_utf8_container_name_with_require_valid_tags_true
562
563
  setup_gce_metadata_stubs
563
- setup_container_metadata_stubs
564
+ setup_k8s_metadata_stubs
564
565
  non_utf8_tags = INVALID_TAGS.select do |tag, _|
565
566
  tag.is_a?(String) && !tag.empty?
566
567
  end
@@ -600,7 +601,7 @@ module BaseTest
600
601
  # Verify that tags extracted from container names are properly encoded.
601
602
  def test_encode_tags_from_container_name_with_require_valid_tags_true
602
603
  setup_gce_metadata_stubs
603
- setup_container_metadata_stubs
604
+ setup_k8s_metadata_stubs
604
605
  VALID_TAGS.each do |tag, encoded_tag|
605
606
  setup_logging_stubs do
606
607
  @logs_sent = []
@@ -639,7 +640,7 @@ module BaseTest
639
640
  # sanitized.
640
641
  def test_sanitize_tags_from_container_name_with_require_valid_tags_false
641
642
  setup_gce_metadata_stubs
642
- setup_container_metadata_stubs
643
+ setup_k8s_metadata_stubs
643
644
  # Log names are derived from container names for containers. And container
644
645
  # names are extracted from the tag based on a regex match pattern. As a
645
646
  # prerequisite, the tag should already be a string, thus we only test
@@ -968,7 +969,7 @@ module BaseTest
968
969
 
969
970
  def test_one_container_log_from_tag_stderr
970
971
  setup_gce_metadata_stubs
971
- setup_container_metadata_stubs
972
+ setup_k8s_metadata_stubs
972
973
  setup_logging_stubs do
973
974
  d = create_driver(APPLICATION_DEFAULT_CONFIG, CONTAINER_TAG)
974
975
  d.emit(container_log_entry(log_entry(0), 'stderr'))
@@ -979,15 +980,15 @@ module BaseTest
979
980
  ) { |_, oldval, newval| oldval.merge(newval) }
980
981
  verify_log_entries(1, expected_params) do |entry, i|
981
982
  verify_default_log_entry_text(entry['textPayload'], i, entry)
982
- assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
983
- assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
983
+ assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
984
+ assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
984
985
  assert_equal 'ERROR', entry['severity'], entry
985
986
  end
986
987
  end
987
988
 
988
989
  def test_json_container_log_metadata_from_plugin
989
990
  setup_gce_metadata_stubs
990
- setup_container_metadata_stubs
991
+ setup_k8s_metadata_stubs
991
992
  setup_logging_stubs do
992
993
  d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
993
994
  d.emit(container_log_entry_with_metadata('{"msg": "test log entry 0", ' \
@@ -1002,15 +1003,15 @@ module BaseTest
1002
1003
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
1003
1004
  assert_equal 'test', get_string(fields['tag2']), entry
1004
1005
  assert_equal 5000, get_number(fields['data']), entry
1005
- assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1006
- assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1006
+ assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1007
+ assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1007
1008
  assert_equal 'WARNING', entry['severity'], entry
1008
1009
  end
1009
1010
  end
1010
1011
 
1011
1012
  def test_json_container_log_metadata_from_tag
1012
1013
  setup_gce_metadata_stubs
1013
- setup_container_metadata_stubs
1014
+ setup_k8s_metadata_stubs
1014
1015
  setup_logging_stubs do
1015
1016
  d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
1016
1017
  d.emit(container_log_entry('{"msg": "test log entry 0", ' \
@@ -1025,8 +1026,8 @@ module BaseTest
1025
1026
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
1026
1027
  assert_equal 'test', get_string(fields['tag2']), entry
1027
1028
  assert_equal 5000, get_number(fields['data']), entry
1028
- assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1029
- assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1029
+ assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1030
+ assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1030
1031
  assert_equal 'WARNING', entry['severity'], entry
1031
1032
  end
1032
1033
  end
@@ -1339,25 +1340,24 @@ module BaseTest
1339
1340
  end
1340
1341
  end
1341
1342
 
1342
- # Test k8s monitored resource including the fallback when Metadata Agent
1343
- # restarts.
1344
- def test_k8s_monitored_resource_fallback
1343
+ # Test k8s_container monitored resource including the fallback when Metadata
1344
+ # Agent restarts.
1345
+ def test_k8s_container_monitored_resource_fallback
1345
1346
  [
1346
- # k8s_container.
1347
1347
  # When enable_metadata_agent is false.
1348
1348
  {
1349
1349
  config: APPLICATION_DEFAULT_CONFIG,
1350
1350
  setup_metadata_agent_stub: false,
1351
1351
  setup_k8s_stub: false,
1352
1352
  log_entry: k8s_container_log_entry(log_entry(0)),
1353
- expected_params: COMPUTE_PARAMS
1353
+ expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1354
1354
  },
1355
1355
  {
1356
1356
  config: APPLICATION_DEFAULT_CONFIG,
1357
1357
  setup_metadata_agent_stub: true,
1358
1358
  setup_k8s_stub: false,
1359
1359
  log_entry: k8s_container_log_entry(log_entry(0)),
1360
- expected_params: COMPUTE_PARAMS
1360
+ expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1361
1361
  },
1362
1362
  {
1363
1363
  config: APPLICATION_DEFAULT_CONFIG,
@@ -1379,7 +1379,7 @@ module BaseTest
1379
1379
  setup_metadata_agent_stub: false,
1380
1380
  setup_k8s_stub: false,
1381
1381
  log_entry: k8s_container_log_entry(log_entry(0)),
1382
- expected_params: COMPUTE_PARAMS
1382
+ expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1383
1383
  },
1384
1384
  {
1385
1385
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1415,7 +1415,30 @@ module BaseTest
1415
1415
  setup_k8s_stub: true,
1416
1416
  log_entry: k8s_container_log_entry(log_entry(0)),
1417
1417
  expected_params: K8S_CONTAINER_PARAMS
1418
- },
1418
+ }
1419
+ ].each do |test_params|
1420
+ new_stub_context do
1421
+ setup_gce_metadata_stubs
1422
+ setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1423
+ setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1424
+ setup_logging_stubs do
1425
+ d = create_driver(test_params[:config], CONTAINER_TAG)
1426
+ d.emit(test_params[:log_entry])
1427
+ d.run
1428
+ end
1429
+ verify_log_entries(1, test_params[:expected_params],
1430
+ 'jsonPayload') do |entry|
1431
+ fields = get_fields(entry['jsonPayload'])
1432
+ assert_equal 2, fields.size, entry
1433
+ assert_equal 'test log entry 0', get_string(fields['log']), entry
1434
+ assert_equal K8S_STREAM, get_string(fields['stream']), entry
1435
+ end
1436
+ end
1437
+ end
1438
+ end
1439
+
1440
+ def test_k8s_container_monitored_resource_invalid_local_resource_id
1441
+ [
1419
1442
  # When local_resource_id is not present or does not match k8s regexes.
1420
1443
  {
1421
1444
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1423,7 +1446,7 @@ module BaseTest
1423
1446
  setup_k8s_stub: true,
1424
1447
  log_entry: k8s_container_log_entry(
1425
1448
  log_entry(0)).reject { |k, _| k == LOCAL_RESOURCE_ID_KEY },
1426
- expected_params: COMPUTE_PARAMS
1449
+ expected_params: CONTAINER_FROM_TAG_PARAMS
1427
1450
  },
1428
1451
  {
1429
1452
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1432,11 +1455,29 @@ module BaseTest
1432
1455
  log_entry: k8s_container_log_entry(
1433
1456
  log_entry(0),
1434
1457
  local_resource_id: RANDOM_LOCAL_RESOURCE_ID),
1435
- # When 'kube-env' is present, "compute.googleapis.com/resource_name" is
1436
- # not added.
1437
- expected_params: COMPUTE_PARAMS
1438
- },
1439
- # Specific cases for k8s_node.
1458
+ expected_params: CONTAINER_FROM_TAG_PARAMS
1459
+ }
1460
+ ].each do |test_params|
1461
+ new_stub_context do
1462
+ setup_gce_metadata_stubs
1463
+ setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1464
+ setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1465
+ setup_logging_stubs do
1466
+ d = create_driver(test_params[:config], CONTAINER_TAG)
1467
+ d.emit(test_params[:log_entry])
1468
+ d.run
1469
+ end
1470
+ verify_log_entries(1, test_params[:expected_params]) do |entry|
1471
+ assert_equal 'test log entry 0', entry['textPayload'], entry
1472
+ end
1473
+ end
1474
+ end
1475
+ end
1476
+
1477
+ # Test k8s_node monitored resource including the fallback when Metadata Agent
1478
+ # restarts.
1479
+ def test_k8s_node_monitored_resource_fallback
1480
+ [
1440
1481
  {
1441
1482
  config: APPLICATION_DEFAULT_CONFIG,
1442
1483
  setup_metadata_agent_stub: true,
@@ -1475,16 +1516,8 @@ module BaseTest
1475
1516
  ].each do |test_params|
1476
1517
  new_stub_context do
1477
1518
  setup_gce_metadata_stubs
1478
- if test_params[:setup_metadata_agent_stub]
1479
- setup_metadata_agent_stubs
1480
- else
1481
- setup_no_metadata_agent_stubs
1482
- end
1483
- if test_params[:setup_k8s_stub]
1484
- setup_k8s_metadata_stubs
1485
- else
1486
- setup_no_k8s_metadata_stubs
1487
- end
1519
+ setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1520
+ setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1488
1521
  setup_logging_stubs do
1489
1522
  d = create_driver(test_params[:config])
1490
1523
  d.emit(test_params[:log_entry])
@@ -1561,7 +1594,7 @@ module BaseTest
1561
1594
  [1, 2, 3, 5, 11, 50].each do |n|
1562
1595
  new_stub_context do
1563
1596
  setup_gce_metadata_stubs
1564
- setup_container_metadata_stubs
1597
+ setup_k8s_metadata_stubs
1565
1598
  setup_metadata_agent_stubs
1566
1599
  setup_logging_stubs do
1567
1600
  d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
@@ -1573,7 +1606,7 @@ module BaseTest
1573
1606
  verify_log_entries(n, CONTAINER_FROM_APPLICATION_PARAMS)
1574
1607
  assert_requested_metadata_agent_stub(
1575
1608
  "#{CONTAINER_LOCAL_RESOURCE_ID_PREFIX}.#{CONTAINER_NAMESPACE_ID}" \
1576
- ".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}")
1609
+ ".#{K8S_POD_NAME}.#{K8S_CONTAINER_NAME}")
1577
1610
  end
1578
1611
  end
1579
1612
  end
@@ -1653,44 +1686,34 @@ module BaseTest
1653
1686
  MANAGED_VM_BACKEND_VERSION)
1654
1687
  end
1655
1688
 
1656
- def setup_container_metadata_stubs
1657
- stub_metadata_request(
1658
- 'instance/attributes/',
1659
- "attribute1\nkube-env\nlast_attribute")
1660
- stub_metadata_request('instance/attributes/kube-env',
1661
- "ENABLE_NODE_LOGGING: \"true\"\n"\
1662
- 'INSTANCE_PREFIX: '\
1663
- "gke-#{CONTAINER_CLUSTER_NAME}-740fdafa\n"\
1664
- 'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
1665
- end
1666
-
1667
- def setup_k8s_metadata_stubs
1668
- stub_metadata_request(
1669
- 'instance/attributes/',
1670
- "attribute1\ncluster-name\ncluster-location\nlast_attribute")
1671
- stub_metadata_request('instance/attributes/cluster-location', K8S_LOCATION2)
1672
- stub_metadata_request('instance/attributes/cluster-name', K8S_CLUSTER_NAME)
1673
- end
1674
-
1675
- def setup_no_k8s_metadata_stubs
1676
- ['cluster-location', 'cluster-name'].each do |metadata_name|
1677
- stub_request(:get, %r{.*instance/attributes/#{metadata_name}.*})
1678
- .to_return(status: 404,
1679
- body: 'The requested URL /computeMetadata/v1/instance/' \
1680
- "attributes/#{metadata_name} was not found on this" \
1681
- ' server.')
1689
+ def setup_k8s_metadata_stubs(should_respond = true)
1690
+ if should_respond
1691
+ stub_metadata_request(
1692
+ 'instance/attributes/',
1693
+ "attribute1\ncluster-location\ncluster-name\nlast_attribute")
1694
+ stub_metadata_request('instance/attributes/cluster-location',
1695
+ K8S_LOCATION2)
1696
+ stub_metadata_request('instance/attributes/cluster-name',
1697
+ K8S_CLUSTER_NAME)
1698
+ else
1699
+ ['cluster-location', 'cluster-name'].each do |metadata_name|
1700
+ stub_request(:get, %r{.*instance/attributes/#{metadata_name}.*})
1701
+ .to_return(status: 404,
1702
+ body: 'The requested URL /computeMetadata/v1/instance/' \
1703
+ "attributes/#{metadata_name} was not found on this" \
1704
+ ' server.')
1705
+ end
1682
1706
  end
1683
1707
  end
1684
1708
 
1685
1709
  def setup_cloudfunctions_metadata_stubs
1686
1710
  stub_metadata_request(
1687
1711
  'instance/attributes/',
1688
- "attribute1\nkube-env\ngcf_region\nlast_attribute")
1689
- stub_metadata_request('instance/attributes/kube-env',
1690
- "ENABLE_NODE_LOGGING: \"true\"\n"\
1691
- 'INSTANCE_PREFIX: '\
1692
- "gke-#{CLOUDFUNCTIONS_CLUSTER_NAME}-740fdafa\n"\
1693
- 'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
1712
+ "attribute1\ncluster-location\ncluster-name\ngcf_region\nlast_attribute")
1713
+ stub_metadata_request('instance/attributes/cluster-location',
1714
+ K8S_LOCATION2)
1715
+ stub_metadata_request('instance/attributes/cluster-name',
1716
+ K8S_CLUSTER_NAME)
1694
1717
  stub_metadata_request('instance/attributes/gcf_region',
1695
1718
  CLOUDFUNCTIONS_REGION)
1696
1719
  end
@@ -1725,19 +1748,20 @@ module BaseTest
1725
1748
  WebMock.reset!
1726
1749
  end
1727
1750
 
1728
- def setup_metadata_agent_stubs
1729
- MONITORED_RESOURCE_STUBS.each do |local_resource_id, resource|
1730
- stub_request(:get, metadata_request_url(local_resource_id))
1731
- .to_return(status: 200, body: resource)
1751
+ def setup_metadata_agent_stubs(should_respond = true)
1752
+ if should_respond
1753
+ MONITORED_RESOURCE_STUBS.each do |local_resource_id, resource|
1754
+ stub_request(:get, metadata_request_url(local_resource_id))
1755
+ .to_return(status: 200, body: resource)
1756
+ end
1757
+ stub_request(:get, metadata_request_url(RANDOM_LOCAL_RESOURCE_ID))
1758
+ .to_return(status: 404, body: '')
1759
+ else
1760
+ # Simulate an environment with no metadata agent endpoint present.
1761
+ stub_request(:get,
1762
+ %r{#{DEFAULT_METADATA_AGENT_URL}\/monitoredResource/.*})
1763
+ .to_raise(Errno::EHOSTUNREACH)
1732
1764
  end
1733
- stub_request(:get, metadata_request_url(RANDOM_LOCAL_RESOURCE_ID))
1734
- .to_return(status: 404, body: '')
1735
- end
1736
-
1737
- def setup_no_metadata_agent_stubs
1738
- # Simulate an environment with no metadata agent endpoint present.
1739
- stub_request(:get, %r{#{DEFAULT_METADATA_AGENT_URL}\/monitoredResource/.*})
1740
- .to_raise(Errno::EHOSTUNREACH)
1741
1765
  end
1742
1766
 
1743
1767
  def assert_requested_metadata_agent_stub(local_resource_id)
@@ -1747,21 +1771,20 @@ module BaseTest
1747
1771
  # GKE Container.
1748
1772
 
1749
1773
  def container_tag_with_container_name(container_name)
1750
- "kubernetes.#{CONTAINER_POD_NAME}_#{CONTAINER_NAMESPACE_NAME}_" \
1751
- "#{container_name}"
1774
+ "kubernetes.#{K8S_POD_NAME}_#{K8S_NAMESPACE_NAME}_#{container_name}"
1752
1775
  end
1753
1776
 
1754
1777
  def container_log_entry_with_metadata(
1755
- log, container_name = CONTAINER_CONTAINER_NAME)
1778
+ log, container_name = K8S_CONTAINER_NAME)
1756
1779
  {
1757
1780
  log: log,
1758
- stream: CONTAINER_STREAM,
1759
- time: CONTAINER_TIMESTAMP,
1781
+ stream: K8S_STREAM,
1782
+ time: K8S_TIMESTAMP,
1760
1783
  kubernetes: {
1761
1784
  namespace_id: CONTAINER_NAMESPACE_ID,
1762
- namespace_name: CONTAINER_NAMESPACE_NAME,
1785
+ namespace_name: K8S_NAMESPACE_NAME,
1763
1786
  pod_id: CONTAINER_POD_ID,
1764
- pod_name: CONTAINER_POD_NAME,
1787
+ pod_name: K8S_POD_NAME,
1765
1788
  container_name: container_name,
1766
1789
  labels: {
1767
1790
  CONTAINER_LABEL_KEY => CONTAINER_LABEL_VALUE
@@ -1770,11 +1793,11 @@ module BaseTest
1770
1793
  }
1771
1794
  end
1772
1795
 
1773
- def container_log_entry(log, stream = CONTAINER_STREAM)
1796
+ def container_log_entry(log, stream = K8S_STREAM)
1774
1797
  {
1775
1798
  log: log,
1776
1799
  stream: stream,
1777
- time: CONTAINER_TIMESTAMP
1800
+ time: K8S_TIMESTAMP
1778
1801
  }
1779
1802
  end
1780
1803
 
@@ -1783,7 +1806,7 @@ module BaseTest
1783
1806
  log: log,
1784
1807
  LOCAL_RESOURCE_ID_KEY =>
1785
1808
  "#{CONTAINER_LOCAL_RESOURCE_ID_PREFIX}.#{CONTAINER_NAMESPACE_ID}" \
1786
- ".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}"
1809
+ ".#{K8S_POD_NAME}.#{K8S_CONTAINER_NAME}"
1787
1810
  }
1788
1811
  end
1789
1812
 
@@ -1949,7 +1972,7 @@ module BaseTest
1949
1972
 
1950
1973
  def verify_container_logs(log_entry_factory, expected_params)
1951
1974
  setup_gce_metadata_stubs
1952
- setup_container_metadata_stubs
1975
+ setup_k8s_metadata_stubs
1953
1976
  [1, 2, 3, 5, 11, 50].each do |n|
1954
1977
  @logs_sent = []
1955
1978
  setup_logging_stubs do
@@ -1959,9 +1982,8 @@ module BaseTest
1959
1982
  end
1960
1983
  verify_log_entries(n, expected_params) do |entry, i|
1961
1984
  verify_default_log_entry_text(entry['textPayload'], i, entry)
1962
- assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'],
1963
- entry
1964
- assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1985
+ assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1986
+ assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1965
1987
  assert_equal CONTAINER_SEVERITY, entry['severity'], entry
1966
1988
  end
1967
1989
  end
@@ -143,20 +143,11 @@ module Constants
143
143
  ".#{K8S_CONTAINER_NAME}".freeze
144
144
 
145
145
  # Container Engine / Kubernetes specific labels.
146
- CONTAINER_CLUSTER_NAME = 'cluster-1'.freeze
147
146
  CONTAINER_NAMESPACE_ID = '898268c8-4a36-11e5-9d81-42010af0194c'.freeze
148
- CONTAINER_NAMESPACE_NAME = 'kube-system'.freeze
149
147
  CONTAINER_POD_ID = 'cad3c3c4-4b9c-11e5-9d81-42010af0194c'.freeze
150
- CONTAINER_POD_NAME = 'redis-master-c0l82.foo.bar'.freeze
151
- CONTAINER_CONTAINER_NAME = 'redis'.freeze
152
148
  CONTAINER_LABEL_KEY = 'component'.freeze
153
149
  CONTAINER_LABEL_VALUE = 'redis-component'.freeze
154
- CONTAINER_STREAM = 'stdout'.freeze
155
150
  CONTAINER_SEVERITY = 'INFO'.freeze
156
- # Timestamp for 1234567890 seconds and 987654321 nanoseconds since epoch.
157
- CONTAINER_TIMESTAMP = '2009-02-13T23:31:30.987654321Z'.freeze
158
- CONTAINER_SECONDS_EPOCH = 1_234_567_890
159
- CONTAINER_NANOS = 987_654_321
160
151
  CONTAINER_LOCAL_RESOURCE_ID_PREFIX = 'gke_container'.freeze
161
152
 
162
153
  # Cloud Functions specific labels.
@@ -408,28 +399,27 @@ module Constants
408
399
 
409
400
  # GKE Container.
410
401
  CONTAINER_TAG =
411
- "kubernetes.#{CONTAINER_POD_NAME}_#{CONTAINER_NAMESPACE_NAME}_" \
412
- "#{CONTAINER_CONTAINER_NAME}".freeze
402
+ "kubernetes.#{K8S_POD_NAME}_#{K8S_NAMESPACE_NAME}_" \
403
+ "#{K8S_CONTAINER_NAME}".freeze
413
404
 
414
405
  CONTAINER_FROM_METADATA_PARAMS = {
415
406
  resource: {
416
407
  type: GKE_CONSTANTS[:resource_type],
417
408
  labels: {
418
- 'cluster_name' => CONTAINER_CLUSTER_NAME,
409
+ 'cluster_name' => K8S_CLUSTER_NAME,
419
410
  'namespace_id' => CONTAINER_NAMESPACE_ID,
420
411
  'instance_id' => VM_ID,
421
412
  'pod_id' => CONTAINER_POD_ID,
422
- 'container_name' => CONTAINER_CONTAINER_NAME,
413
+ 'container_name' => K8S_CONTAINER_NAME,
423
414
  'zone' => ZONE
424
415
  }
425
416
  },
426
- log_name: CONTAINER_CONTAINER_NAME,
417
+ log_name: K8S_CONTAINER_NAME,
427
418
  project_id: PROJECT_ID,
428
419
  labels: {
429
- "#{GKE_CONSTANTS[:service]}/namespace_name" =>
430
- CONTAINER_NAMESPACE_NAME,
431
- "#{GKE_CONSTANTS[:service]}/pod_name" => CONTAINER_POD_NAME,
432
- "#{GKE_CONSTANTS[:service]}/stream" => CONTAINER_STREAM,
420
+ "#{GKE_CONSTANTS[:service]}/namespace_name" => K8S_NAMESPACE_NAME,
421
+ "#{GKE_CONSTANTS[:service]}/pod_name" => K8S_POD_NAME,
422
+ "#{GKE_CONSTANTS[:service]}/stream" => K8S_STREAM,
433
423
  "label/#{CONTAINER_LABEL_KEY}" => CONTAINER_LABEL_VALUE,
434
424
  "#{COMPUTE_CONSTANTS[:service]}/resource_name" => HOSTNAME
435
425
  }
@@ -441,21 +431,20 @@ module Constants
441
431
  resource: {
442
432
  type: GKE_CONSTANTS[:resource_type],
443
433
  labels: {
444
- 'cluster_name' => CONTAINER_CLUSTER_NAME,
445
- 'namespace_id' => CONTAINER_NAMESPACE_NAME,
434
+ 'cluster_name' => K8S_CLUSTER_NAME,
435
+ 'namespace_id' => K8S_NAMESPACE_NAME,
446
436
  'instance_id' => VM_ID,
447
- 'pod_id' => CONTAINER_POD_NAME,
448
- 'container_name' => CONTAINER_CONTAINER_NAME,
437
+ 'pod_id' => K8S_POD_NAME,
438
+ 'container_name' => K8S_CONTAINER_NAME,
449
439
  'zone' => ZONE
450
440
  }
451
441
  },
452
- log_name: CONTAINER_CONTAINER_NAME,
442
+ log_name: K8S_CONTAINER_NAME,
453
443
  project_id: PROJECT_ID,
454
444
  labels: {
455
- "#{GKE_CONSTANTS[:service]}/namespace_name" =>
456
- CONTAINER_NAMESPACE_NAME,
457
- "#{GKE_CONSTANTS[:service]}/pod_name" => CONTAINER_POD_NAME,
458
- "#{GKE_CONSTANTS[:service]}/stream" => CONTAINER_STREAM,
445
+ "#{GKE_CONSTANTS[:service]}/namespace_name" => K8S_NAMESPACE_NAME,
446
+ "#{GKE_CONSTANTS[:service]}/pod_name" => K8S_POD_NAME,
447
+ "#{GKE_CONSTANTS[:service]}/stream" => K8S_STREAM,
459
448
  "#{COMPUTE_CONSTANTS[:service]}/resource_name" => HOSTNAME
460
449
  }
461
450
  }.freeze
@@ -464,11 +453,11 @@ module Constants
464
453
  resource: {
465
454
  type: GKE_CONSTANTS[:resource_type],
466
455
  labels: {
467
- 'cluster_name' => CONTAINER_CLUSTER_NAME,
456
+ 'cluster_name' => K8S_CLUSTER_NAME,
468
457
  'namespace_id' => CONTAINER_NAMESPACE_ID,
469
458
  'instance_id' => VM_ID,
470
459
  'pod_id' => CONTAINER_POD_ID,
471
- 'container_name' => CONTAINER_CONTAINER_NAME,
460
+ 'container_name' => K8S_CONTAINER_NAME,
472
461
  'zone' => ZONE
473
462
  }
474
463
  },
@@ -491,7 +480,6 @@ module Constants
491
480
  'location' => K8S_LOCATION
492
481
  }
493
482
  },
494
- log_name: 'test',
495
483
  project_id: PROJECT_ID,
496
484
  labels: {}
497
485
  }.freeze
@@ -510,6 +498,10 @@ module Constants
510
498
  )
511
499
  )
512
500
  ).freeze
501
+ # Used in k8s fallback tests.
502
+ K8S_CONTAINER_PARAMS_FROM_FALLBACK = COMPUTE_PARAMS_NO_LOG_NAME.merge(
503
+ log_name: CONTAINER_TAG
504
+ ).freeze
513
505
 
514
506
  # K8s Node.
515
507
  K8S_NODE_PARAMS = {
@@ -785,12 +777,12 @@ module Constants
785
777
  }.to_json,
786
778
  # GKE container logs.
787
779
  "#{CONTAINER_LOCAL_RESOURCE_ID_PREFIX}.#{CONTAINER_NAMESPACE_ID}" \
788
- ".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}" =>
780
+ ".#{K8S_POD_NAME}.#{K8S_CONTAINER_NAME}" =>
789
781
  {
790
782
  'type' => GKE_CONSTANTS[:resource_type],
791
783
  'labels' => {
792
- 'cluster_name' => CONTAINER_CLUSTER_NAME,
793
- 'container_name' => CONTAINER_CONTAINER_NAME,
784
+ 'cluster_name' => K8S_CLUSTER_NAME,
785
+ 'container_name' => K8S_CONTAINER_NAME,
794
786
  'instance_id' => VM_ID,
795
787
  'namespace_id' => CONTAINER_NAMESPACE_ID,
796
788
  'pod_id' => CONTAINER_POD_ID,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-google-cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.24
4
+ version: 0.6.25.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stackdriver Agents Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-05 00:00:00.000000000 Z
11
+ date: 2018-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -106,14 +106,14 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '1.8'
109
+ version: '2.1'
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '1.8'
116
+ version: '2.1'
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: google-protobuf
119
119
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +231,7 @@ extra_rdoc_files: []
231
231
  files:
232
232
  - CONTRIBUTING
233
233
  - Gemfile
234
+ - Gemfile.lock
234
235
  - LICENSE
235
236
  - README.rdoc
236
237
  - Rakefile
@@ -265,9 +266,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
265
266
  version: '2.2'
266
267
  required_rubygems_version: !ruby/object:Gem::Requirement
267
268
  requirements:
268
- - - ">="
269
+ - - ">"
269
270
  - !ruby/object:Gem::Version
270
- version: '0'
271
+ version: 1.3.1
271
272
  requirements: []
272
273
  rubyforge_project:
273
274
  rubygems_version: 2.6.14