fluent-plugin-google-cloud 0.4.15 → 0.4.16
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.
- data/Gemfile.lock +16 -15
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/out_google_cloud.rb +71 -70
- data/test/plugin/test_out_google_cloud.rb +84 -69
- metadata +35 -13
- checksums.yaml +0 -15
data/Gemfile.lock
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.4.
|
4
|
+
fluent-plugin-google-cloud (0.4.16)
|
5
5
|
fluentd (~> 0.10)
|
6
6
|
google-api-client (>= 0.8.6, < 0.9)
|
7
7
|
googleauth (~> 0.4)
|
8
8
|
json (~> 1.8)
|
9
|
-
jwt (< 1.5.3)
|
10
9
|
|
11
10
|
GEM
|
12
11
|
remote: https://rubygems.org/
|
13
12
|
specs:
|
14
|
-
activesupport (4.2.
|
13
|
+
activesupport (4.2.4)
|
15
14
|
i18n (~> 0.7)
|
16
15
|
json (~> 1.7, >= 1.7.7)
|
17
16
|
minitest (~> 5.1)
|
@@ -25,13 +24,13 @@ GEM
|
|
25
24
|
addressable (>= 2.3.1)
|
26
25
|
extlib (>= 0.9.15)
|
27
26
|
multi_json (>= 1.0.0)
|
28
|
-
cool.io (1.4.
|
27
|
+
cool.io (1.4.1)
|
29
28
|
crack (0.4.2)
|
30
29
|
safe_yaml (~> 1.0.0)
|
31
30
|
extlib (0.9.16)
|
32
31
|
faraday (0.9.2)
|
33
32
|
multipart-post (>= 1.2, < 3)
|
34
|
-
fluentd (0.12.
|
33
|
+
fluentd (0.12.16)
|
35
34
|
cool.io (>= 1.2.2, < 2.0.0)
|
36
35
|
http_parser.rb (>= 0.5.1, < 0.7.0)
|
37
36
|
json (>= 1.4.3)
|
@@ -52,14 +51,13 @@ GEM
|
|
52
51
|
multi_json (~> 1.10)
|
53
52
|
retriable (~> 1.4)
|
54
53
|
signet (~> 0.6)
|
55
|
-
googleauth (0.
|
54
|
+
googleauth (0.4.2)
|
56
55
|
faraday (~> 0.9)
|
57
56
|
jwt (~> 1.4)
|
58
57
|
logging (~> 2.0)
|
59
58
|
memoist (~> 0.12)
|
60
59
|
multi_json (~> 1.11)
|
61
|
-
|
62
|
-
signet (~> 0.7)
|
60
|
+
signet (~> 0.6)
|
63
61
|
hashdiff (0.2.2)
|
64
62
|
http_parser.rb (0.6.0)
|
65
63
|
i18n (0.7.0)
|
@@ -68,18 +66,17 @@ GEM
|
|
68
66
|
launchy (2.4.3)
|
69
67
|
addressable (~> 2.3)
|
70
68
|
little-plugger (1.1.4)
|
71
|
-
logging (2.
|
69
|
+
logging (2.0.0)
|
72
70
|
little-plugger (~> 1.1)
|
73
71
|
multi_json (~> 1.10)
|
74
|
-
memoist (0.
|
72
|
+
memoist (0.12.0)
|
75
73
|
metaclass (0.0.4)
|
76
|
-
minitest (5.8.
|
74
|
+
minitest (5.8.2)
|
77
75
|
mocha (1.1.0)
|
78
76
|
metaclass (~> 0.0.1)
|
79
77
|
msgpack (0.5.12)
|
80
78
|
multi_json (1.11.2)
|
81
79
|
multipart-post (2.0.0)
|
82
|
-
os (0.9.6)
|
83
80
|
parser (2.2.3.0)
|
84
81
|
ast (>= 1.1, < 3.0)
|
85
82
|
power_assert (0.2.5)
|
@@ -95,9 +92,10 @@ GEM
|
|
95
92
|
ruby-progressbar (~> 1.4)
|
96
93
|
ruby-progressbar (1.7.5)
|
97
94
|
safe_yaml (1.0.4)
|
98
|
-
sigdump (0.2.
|
99
|
-
signet (0.
|
95
|
+
sigdump (0.2.3)
|
96
|
+
signet (0.6.1)
|
100
97
|
addressable (~> 2.3)
|
98
|
+
extlib (~> 0.9)
|
101
99
|
faraday (~> 0.9)
|
102
100
|
jwt (~> 1.5)
|
103
101
|
multi_json (~> 1.10)
|
@@ -107,7 +105,7 @@ GEM
|
|
107
105
|
thread_safe (0.3.5)
|
108
106
|
tzinfo (1.2.2)
|
109
107
|
thread_safe (~> 0.1)
|
110
|
-
tzinfo-data (1.
|
108
|
+
tzinfo-data (1.2015.7)
|
111
109
|
tzinfo (>= 1.0.0)
|
112
110
|
webmock (1.22.3)
|
113
111
|
addressable (>= 2.3.6)
|
@@ -125,3 +123,6 @@ DEPENDENCIES
|
|
125
123
|
rubocop (= 0.34.2)
|
126
124
|
test-unit (~> 3.0)
|
127
125
|
webmock (~> 1.17)
|
126
|
+
|
127
|
+
BUNDLED WITH
|
128
|
+
1.10.6
|
@@ -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.4.
|
13
|
+
gem.version = '0.4.16'
|
14
14
|
gem.authors = ['Todd Derr', 'Alex Robinson']
|
15
15
|
gem.email = ['salty@google.com']
|
16
16
|
|
@@ -11,12 +11,23 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
|
+
require 'cgi'
|
15
|
+
require 'google/api_client'
|
16
|
+
require 'google/api_client/auth/compute_service_account'
|
17
|
+
require 'googleauth'
|
18
|
+
require 'json'
|
19
|
+
require 'open-uri'
|
20
|
+
require 'socket'
|
21
|
+
require 'yaml'
|
14
22
|
|
15
23
|
module Fluent
|
16
24
|
# fluentd output plugin for the Google Cloud Logging API
|
17
25
|
class GoogleCloudOutput < BufferedOutput
|
18
26
|
Fluent::Plugin.register_output('google_cloud', self)
|
19
27
|
|
28
|
+
PLUGIN_NAME = 'Fluentd Google Cloud Logging plugin'
|
29
|
+
PLUGIN_VERSION = '0.4.16'
|
30
|
+
|
20
31
|
# Constants for service names.
|
21
32
|
APPENGINE_SERVICE = 'appengine.googleapis.com'
|
22
33
|
CLOUDFUNCTIONS_SERVICE = 'cloudfunctions.googleapis.com'
|
@@ -123,15 +134,6 @@ module Fluent
|
|
123
134
|
|
124
135
|
def initialize
|
125
136
|
super
|
126
|
-
require 'cgi'
|
127
|
-
require 'google/api_client'
|
128
|
-
require 'google/api_client/auth/compute_service_account'
|
129
|
-
require 'googleauth'
|
130
|
-
require 'json'
|
131
|
-
require 'open-uri'
|
132
|
-
require 'socket'
|
133
|
-
require 'yaml'
|
134
|
-
|
135
137
|
# use the global logger
|
136
138
|
@log = $log # rubocop:disable Style/GlobalVars
|
137
139
|
end
|
@@ -290,9 +292,7 @@ module Fluent
|
|
290
292
|
|
291
293
|
def start
|
292
294
|
super
|
293
|
-
|
294
295
|
init_api_client
|
295
|
-
|
296
296
|
@successful_call = false
|
297
297
|
@timenanos_warning = false
|
298
298
|
end
|
@@ -314,10 +314,9 @@ module Fluent
|
|
314
314
|
end
|
315
315
|
|
316
316
|
grouped_entries.each do |tag, arr|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
}
|
317
|
+
entries = []
|
318
|
+
labels = @common_labels.clone
|
319
|
+
|
321
320
|
if @running_cloudfunctions
|
322
321
|
# If the current group of entries is coming from a Cloud Functions
|
323
322
|
# function, the function name can be extracted from the tag.
|
@@ -326,7 +325,6 @@ module Fluent
|
|
326
325
|
# Service name is set to Cloud Functions only for logs actually
|
327
326
|
# coming from a function.
|
328
327
|
@service_name = CLOUDFUNCTIONS_SERVICE
|
329
|
-
labels = write_log_entries_request['commonLabels']
|
330
328
|
labels["#{CLOUDFUNCTIONS_SERVICE}/region"] = @gcf_region
|
331
329
|
labels["#{CLOUDFUNCTIONS_SERVICE}/function_name"] =
|
332
330
|
decode_cloudfunctions_function_name(
|
@@ -343,7 +341,6 @@ module Fluent
|
|
343
341
|
# Do this here to avoid having to repeat it for each record.
|
344
342
|
match_data = @compiled_kubernetes_tag_regexp.match(tag)
|
345
343
|
if match_data
|
346
|
-
labels = write_log_entries_request['commonLabels']
|
347
344
|
%w(namespace_name pod_name container_name).each do |field|
|
348
345
|
labels["#{CONTAINER_SERVICE}/#{field}"] = match_data[field]
|
349
346
|
end
|
@@ -397,48 +394,8 @@ module Fluent
|
|
397
394
|
end
|
398
395
|
end
|
399
396
|
|
400
|
-
|
401
|
-
record['timestamp'].is_a?(Hash) &&
|
402
|
-
record['timestamp'].key?('seconds') &&
|
403
|
-
record['timestamp'].key?('nanos')
|
404
|
-
ts_secs = record['timestamp']['seconds']
|
405
|
-
ts_nanos = record['timestamp']['nanos']
|
406
|
-
record.delete('timestamp')
|
407
|
-
elsif record.key?('timestampSeconds') &&
|
408
|
-
record.key?('timestampNanos')
|
409
|
-
ts_secs = record['timestampSeconds']
|
410
|
-
ts_nanos = record['timestampNanos']
|
411
|
-
record.delete('timestampSeconds')
|
412
|
-
record.delete('timestampNanos')
|
413
|
-
elsif record.key?('timeNanos')
|
414
|
-
# This is deprecated since the precision is insufficient.
|
415
|
-
# Use timestampSeconds/timestampNanos instead
|
416
|
-
ts_secs = (record['timeNanos'] / 1_000_000_000).to_i
|
417
|
-
ts_nanos = record['timeNanos'] % 1_000_000_000
|
418
|
-
record.delete('timeNanos')
|
419
|
-
unless @timenanos_warning
|
420
|
-
# Warn the user this is deprecated, but only once to avoid spam.
|
421
|
-
@timenanos_warning = true
|
422
|
-
@log.warn 'timeNanos is deprecated - please use ' \
|
423
|
-
'timestampSeconds and timestampNanos instead.'
|
424
|
-
end
|
425
|
-
elsif @service_name == CLOUDFUNCTIONS_SERVICE &&
|
426
|
-
@cloudfunctions_log_match
|
427
|
-
timestamp = DateTime.parse(@cloudfunctions_log_match['timestamp'])
|
428
|
-
ts_secs = timestamp.strftime('%s')
|
429
|
-
ts_nanos = timestamp.strftime('%N')
|
430
|
-
else
|
431
|
-
timestamp = Time.at(time)
|
432
|
-
ts_secs = timestamp.tv_sec
|
433
|
-
ts_nanos = timestamp.tv_nsec
|
434
|
-
end
|
435
|
-
entry['metadata']['timestamp'] = {
|
436
|
-
'seconds' => ts_secs,
|
437
|
-
'nanos' => ts_nanos
|
438
|
-
}
|
439
|
-
|
397
|
+
set_timestamp(record, entry, time)
|
440
398
|
set_severity(record, entry)
|
441
|
-
|
442
399
|
set_http_request(record, entry)
|
443
400
|
|
444
401
|
# If a field is present in the label_map, send its value as a label
|
@@ -464,22 +421,25 @@ module Fluent
|
|
464
421
|
entry['metadata'].delete('labels')
|
465
422
|
end
|
466
423
|
|
467
|
-
|
424
|
+
entries.push(entry)
|
468
425
|
end
|
469
426
|
# Don't send an empty request if we rejected all the entries.
|
470
|
-
next if
|
427
|
+
next if entries.empty?
|
471
428
|
|
472
|
-
log_name = CGI.escape(
|
473
|
-
log_name(tag, write_log_entries_request['commonLabels']))
|
429
|
+
log_name = CGI.escape(log_name(tag, labels))
|
474
430
|
url = 'https://logging.googleapis.com/v1beta3/projects/' \
|
475
431
|
"#{@project_id}/logs/#{log_name}/entries:write"
|
432
|
+
|
476
433
|
begin
|
477
434
|
client = api_client
|
478
435
|
request = client.generate_request(
|
479
436
|
uri: url,
|
480
|
-
body_object: write_log_entries_request,
|
481
437
|
http_method: 'POST',
|
482
|
-
authenticated: true
|
438
|
+
authenticated: true,
|
439
|
+
body_object: {
|
440
|
+
'commonLabels' => labels,
|
441
|
+
'entries' => entries
|
442
|
+
}
|
483
443
|
)
|
484
444
|
client.execute!(request)
|
485
445
|
# Let the user explicitly know when the first call succeeded,
|
@@ -496,11 +456,11 @@ module Fluent
|
|
496
456
|
# should not be retried, unless it is an authentication issue, in
|
497
457
|
# which case we will retry the request via re-raising the exception.
|
498
458
|
raise error if retriable_client_error?(error)
|
499
|
-
log_write_failure(
|
459
|
+
log_write_failure(entries.length, error)
|
500
460
|
rescue JSON::GeneratorError => error
|
501
461
|
# This happens if the request contains illegal characters;
|
502
462
|
# do not retry it because it will fail repeatedly.
|
503
|
-
log_write_failure(
|
463
|
+
log_write_failure(entries.length, error)
|
504
464
|
end
|
505
465
|
end
|
506
466
|
end
|
@@ -519,8 +479,7 @@ module Fluent
|
|
519
479
|
RETRIABLE_CLIENT_ERRORS.include?(error.message)
|
520
480
|
end
|
521
481
|
|
522
|
-
def log_write_failure(
|
523
|
-
dropped = request['entries'].length
|
482
|
+
def log_write_failure(dropped, error)
|
524
483
|
@log.warn "Dropping #{dropped} log message(s)",
|
525
484
|
error_class: error.class.to_s, error: error.to_s
|
526
485
|
end
|
@@ -641,6 +600,48 @@ module Fluent
|
|
641
600
|
instance_prefix
|
642
601
|
end
|
643
602
|
|
603
|
+
def set_timestamp(record, entry, time)
|
604
|
+
if record.key?('timestamp') &&
|
605
|
+
record['timestamp'].is_a?(Hash) &&
|
606
|
+
record['timestamp'].key?('seconds') &&
|
607
|
+
record['timestamp'].key?('nanos')
|
608
|
+
ts_secs = record['timestamp']['seconds']
|
609
|
+
ts_nanos = record['timestamp']['nanos']
|
610
|
+
record.delete('timestamp')
|
611
|
+
elsif record.key?('timestampSeconds') &&
|
612
|
+
record.key?('timestampNanos')
|
613
|
+
ts_secs = record['timestampSeconds']
|
614
|
+
ts_nanos = record['timestampNanos']
|
615
|
+
record.delete('timestampSeconds')
|
616
|
+
record.delete('timestampNanos')
|
617
|
+
elsif record.key?('timeNanos')
|
618
|
+
# This is deprecated since the precision is insufficient.
|
619
|
+
# Use timestampSeconds/timestampNanos instead
|
620
|
+
ts_secs = (record['timeNanos'] / 1_000_000_000).to_i
|
621
|
+
ts_nanos = record['timeNanos'] % 1_000_000_000
|
622
|
+
record.delete('timeNanos')
|
623
|
+
unless @timenanos_warning
|
624
|
+
# Warn the user this is deprecated, but only once to avoid spam.
|
625
|
+
@timenanos_warning = true
|
626
|
+
@log.warn 'timeNanos is deprecated - please use ' \
|
627
|
+
'timestampSeconds and timestampNanos instead.'
|
628
|
+
end
|
629
|
+
elsif @service_name == CLOUDFUNCTIONS_SERVICE &&
|
630
|
+
@cloudfunctions_log_match
|
631
|
+
timestamp = DateTime.parse(@cloudfunctions_log_match['timestamp'])
|
632
|
+
ts_secs = timestamp.strftime('%s')
|
633
|
+
ts_nanos = timestamp.strftime('%N')
|
634
|
+
else
|
635
|
+
timestamp = Time.at(time)
|
636
|
+
ts_secs = timestamp.tv_sec
|
637
|
+
ts_nanos = timestamp.tv_nsec
|
638
|
+
end
|
639
|
+
entry['metadata']['timestamp'] = {
|
640
|
+
'seconds' => ts_secs,
|
641
|
+
'nanos' => ts_nanos
|
642
|
+
}
|
643
|
+
end
|
644
|
+
|
644
645
|
def set_severity(record, entry)
|
645
646
|
if @service_name == CLOUDFUNCTIONS_SERVICE
|
646
647
|
if @cloudfunctions_log_match && @cloudfunctions_log_match['severity']
|
@@ -808,8 +809,8 @@ module Fluent
|
|
808
809
|
|
809
810
|
def init_api_client
|
810
811
|
@client = Google::APIClient.new(
|
811
|
-
application_name:
|
812
|
-
application_version:
|
812
|
+
application_name: PLUGIN_NAME,
|
813
|
+
application_version: PLUGIN_VERSION,
|
813
814
|
retries: 1)
|
814
815
|
|
815
816
|
if @auth_method == 'private_key'
|
@@ -21,7 +21,18 @@ require 'webmock/test_unit'
|
|
21
21
|
class GoogleCloudOutputTest < Test::Unit::TestCase
|
22
22
|
def setup
|
23
23
|
Fluent::Test.setup
|
24
|
+
# delete environment variables that googleauth uses to find credentials.
|
24
25
|
ENV.delete('GOOGLE_APPLICATION_CREDENTIALS')
|
26
|
+
# service account env.
|
27
|
+
ENV.delete('PRIVATE_KEY_VAR')
|
28
|
+
ENV.delete('CLIENT_EMAIL_VAR')
|
29
|
+
# authorized_user env.
|
30
|
+
ENV.delete('CLIENT_ID_VAR')
|
31
|
+
ENV.delete('CLIENT_SECRET_VAR')
|
32
|
+
ENV.delete('REFRESH_TOKEN_VAR')
|
33
|
+
# home var, which is used to find $HOME/.gcloud/...
|
34
|
+
ENV.delete('HOME')
|
35
|
+
|
25
36
|
setup_auth_stubs
|
26
37
|
@logs_sent = []
|
27
38
|
end
|
@@ -88,16 +99,16 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
88
99
|
# path: Path to the credentials file.
|
89
100
|
# project_id: ID of the project, which must correspond to the file contents.
|
90
101
|
IAM_CREDENTIALS = {
|
91
|
-
|
92
|
-
|
102
|
+
path: 'test/plugin/data/iam-credentials.json',
|
103
|
+
project_id: 'fluent-test-project'
|
93
104
|
}
|
94
105
|
LEGACY_CREDENTIALS = {
|
95
|
-
|
96
|
-
|
106
|
+
path: 'test/plugin/data/credentials.json',
|
107
|
+
project_id: '847859579879'
|
97
108
|
}
|
98
109
|
INVALID_CREDENTIALS = {
|
99
|
-
|
100
|
-
|
110
|
+
path: 'test/plugin/data/invalid_credentials.json',
|
111
|
+
project_id: ''
|
101
112
|
}
|
102
113
|
|
103
114
|
# Configuration files for various test scenarios
|
@@ -167,11 +178,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
167
178
|
EC2_SERVICE_NAME = 'ec2.amazonaws.com'
|
168
179
|
|
169
180
|
COMPUTE_PARAMS = {
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
181
|
+
service_name: COMPUTE_SERVICE_NAME,
|
182
|
+
log_name: 'test',
|
183
|
+
project_id: PROJECT_ID,
|
184
|
+
zone: ZONE,
|
185
|
+
labels: {
|
175
186
|
"#{COMPUTE_SERVICE_NAME}/resource_type" => 'instance',
|
176
187
|
"#{COMPUTE_SERVICE_NAME}/resource_id" => VM_ID,
|
177
188
|
"#{COMPUTE_SERVICE_NAME}/resource_name" => HOSTNAME
|
@@ -179,11 +190,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
179
190
|
}
|
180
191
|
|
181
192
|
VMENGINE_PARAMS = {
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
193
|
+
service_name: APPENGINE_SERVICE_NAME,
|
194
|
+
log_name: "#{APPENGINE_SERVICE_NAME}%2Ftest",
|
195
|
+
project_id: PROJECT_ID,
|
196
|
+
zone: ZONE,
|
197
|
+
labels: {
|
187
198
|
"#{APPENGINE_SERVICE_NAME}/module_id" => MANAGED_VM_BACKEND_NAME,
|
188
199
|
"#{APPENGINE_SERVICE_NAME}/version_id" => MANAGED_VM_BACKEND_VERSION,
|
189
200
|
"#{COMPUTE_SERVICE_NAME}/resource_type" => 'instance',
|
@@ -196,11 +207,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
196
207
|
"#{CONTAINER_NAMESPACE_NAME}_#{CONTAINER_CONTAINER_NAME}"
|
197
208
|
|
198
209
|
CONTAINER_FROM_METADATA_PARAMS = {
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
210
|
+
service_name: CONTAINER_SERVICE_NAME,
|
211
|
+
log_name: CONTAINER_CONTAINER_NAME,
|
212
|
+
project_id: PROJECT_ID,
|
213
|
+
zone: ZONE,
|
214
|
+
labels: {
|
204
215
|
"#{CONTAINER_SERVICE_NAME}/instance_id" => VM_ID,
|
205
216
|
"#{CONTAINER_SERVICE_NAME}/cluster_name" => CONTAINER_CLUSTER_NAME,
|
206
217
|
"#{CONTAINER_SERVICE_NAME}/namespace_name" => CONTAINER_NAMESPACE_NAME,
|
@@ -218,11 +229,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
218
229
|
|
219
230
|
# Almost the same as from metadata, but missing namespace_id and pod_id.
|
220
231
|
CONTAINER_FROM_TAG_PARAMS = {
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
232
|
+
service_name: CONTAINER_SERVICE_NAME,
|
233
|
+
log_name: CONTAINER_CONTAINER_NAME,
|
234
|
+
project_id: PROJECT_ID,
|
235
|
+
zone: ZONE,
|
236
|
+
labels: {
|
226
237
|
"#{CONTAINER_SERVICE_NAME}/instance_id" => VM_ID,
|
227
238
|
"#{CONTAINER_SERVICE_NAME}/cluster_name" => CONTAINER_CLUSTER_NAME,
|
228
239
|
"#{CONTAINER_SERVICE_NAME}/namespace_name" => CONTAINER_NAMESPACE_NAME,
|
@@ -240,11 +251,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
240
251
|
"#{CLOUDFUNCTIONS_CONTAINER_NAME}"
|
241
252
|
|
242
253
|
CLOUDFUNCTIONS_PARAMS = {
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
254
|
+
service_name: CLOUDFUNCTIONS_SERVICE_NAME,
|
255
|
+
log_name: 'cloud-functions',
|
256
|
+
project_id: PROJECT_ID,
|
257
|
+
zone: ZONE,
|
258
|
+
labels: {
|
248
259
|
'execution_id' => CLOUDFUNCTIONS_EXECUTION_ID,
|
249
260
|
"#{CLOUDFUNCTIONS_SERVICE_NAME}/function_name" =>
|
250
261
|
CLOUDFUNCTIONS_FUNCTION_NAME,
|
@@ -258,11 +269,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
258
269
|
}
|
259
270
|
|
260
271
|
CLOUDFUNCTIONS_TEXT_NOT_MATCHED_PARAMS = {
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
272
|
+
service_name: CLOUDFUNCTIONS_SERVICE_NAME,
|
273
|
+
log_name: 'cloud-functions',
|
274
|
+
project_id: PROJECT_ID,
|
275
|
+
zone: ZONE,
|
276
|
+
labels: {
|
266
277
|
"#{CLOUDFUNCTIONS_SERVICE_NAME}/function_name" =>
|
267
278
|
CLOUDFUNCTIONS_FUNCTION_NAME,
|
268
279
|
"#{CLOUDFUNCTIONS_SERVICE_NAME}/region" => CLOUDFUNCTIONS_REGION,
|
@@ -275,11 +286,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
275
286
|
}
|
276
287
|
|
277
288
|
CUSTOM_PARAMS = {
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
289
|
+
service_name: COMPUTE_SERVICE_NAME,
|
290
|
+
log_name: 'test',
|
291
|
+
project_id: CUSTOM_PROJECT_ID,
|
292
|
+
zone: CUSTOM_ZONE,
|
293
|
+
labels: {
|
283
294
|
"#{COMPUTE_SERVICE_NAME}/resource_type" => 'instance',
|
284
295
|
"#{COMPUTE_SERVICE_NAME}/resource_id" => CUSTOM_VM_ID,
|
285
296
|
"#{COMPUTE_SERVICE_NAME}/resource_name" => CUSTOM_HOSTNAME
|
@@ -287,11 +298,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
287
298
|
}
|
288
299
|
|
289
300
|
EC2_PARAMS = {
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
301
|
+
service_name: EC2_SERVICE_NAME,
|
302
|
+
log_name: 'test',
|
303
|
+
project_id: EC2_PROJECT_ID,
|
304
|
+
zone: EC2_PREFIXED_ZONE,
|
305
|
+
labels: {
|
295
306
|
"#{EC2_SERVICE_NAME}/resource_type" => 'instance',
|
296
307
|
"#{EC2_SERVICE_NAME}/resource_id" => EC2_VM_ID,
|
297
308
|
"#{EC2_SERVICE_NAME}/account_id" => EC2_ACCOUNT_ID,
|
@@ -516,10 +527,10 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
516
527
|
def test_ec2_metadata_project_id_from_credentials
|
517
528
|
setup_ec2_metadata_stubs
|
518
529
|
[IAM_CREDENTIALS, LEGACY_CREDENTIALS].each do |creds|
|
519
|
-
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = creds[
|
530
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = creds[:path]
|
520
531
|
d = create_driver
|
521
532
|
d.run
|
522
|
-
assert_equal creds[
|
533
|
+
assert_equal creds[:project_id], d.instance.project_id
|
523
534
|
end
|
524
535
|
end
|
525
536
|
|
@@ -535,7 +546,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
535
546
|
def test_one_log_with_json_credentials
|
536
547
|
setup_gce_metadata_stubs
|
537
548
|
setup_logging_stubs
|
538
|
-
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[
|
549
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[:path]
|
539
550
|
d = create_driver
|
540
551
|
d.emit('message' => log_entry(0))
|
541
552
|
d.run
|
@@ -545,7 +556,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
545
556
|
def test_one_log_with_invalid_json_credentials
|
546
557
|
setup_gce_metadata_stubs
|
547
558
|
setup_logging_stubs
|
548
|
-
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = INVALID_CREDENTIALS[
|
559
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = INVALID_CREDENTIALS[:path]
|
549
560
|
d = create_driver
|
550
561
|
d.emit('message' => log_entry(0))
|
551
562
|
exception_count = 0
|
@@ -571,7 +582,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
571
582
|
# don't set up any metadata stubs, so the test will fail if we try to
|
572
583
|
# fetch metadata (and explicitly check this as well).
|
573
584
|
Fluent::GoogleCloudOutput.any_instance.expects(:fetch_metadata).never
|
574
|
-
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[
|
585
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[:path]
|
575
586
|
setup_logging_stubs
|
576
587
|
d = create_driver(NO_METADATA_SERVICE_CONFIG + CUSTOM_METADATA_CONFIG)
|
577
588
|
d.emit('message' => log_entry(0))
|
@@ -580,7 +591,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
580
591
|
end
|
581
592
|
|
582
593
|
def test_one_log_ec2
|
583
|
-
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[
|
594
|
+
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = IAM_CREDENTIALS[:path]
|
584
595
|
setup_ec2_metadata_stubs
|
585
596
|
setup_logging_stubs
|
586
597
|
d = create_driver(CONFIG_EC2_PROJECT_ID)
|
@@ -695,7 +706,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
695
706
|
d.run
|
696
707
|
# make a deep copy of COMPUTE_PARAMS and add the parsed label.
|
697
708
|
params = Marshal.load(Marshal.dump(COMPUTE_PARAMS))
|
698
|
-
params[
|
709
|
+
params[:labels]['sent_label'] = 'label_value'
|
699
710
|
verify_log_entries(1, params)
|
700
711
|
end
|
701
712
|
|
@@ -708,7 +719,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
708
719
|
d.run
|
709
720
|
# make a deep copy of COMPUTE_PARAMS and add the parsed label.
|
710
721
|
params = Marshal.load(Marshal.dump(COMPUTE_PARAMS))
|
711
|
-
params[
|
722
|
+
params[:labels]['sent_label'] = '123456789'
|
712
723
|
verify_log_entries(1, params)
|
713
724
|
end
|
714
725
|
|
@@ -724,7 +735,7 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
724
735
|
d.run
|
725
736
|
# make a deep copy of COMPUTE_PARAMS and add the parsed label.
|
726
737
|
params = Marshal.load(Marshal.dump(COMPUTE_PARAMS))
|
727
|
-
params[
|
738
|
+
params[:labels]['sent_label'] = '{"k1"=>10, "k2"=>"val"}'
|
728
739
|
verify_log_entries(1, params)
|
729
740
|
end
|
730
741
|
|
@@ -748,9 +759,9 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
748
759
|
d.run
|
749
760
|
# make a deep copy of COMPUTE_PARAMS and add the parsed labels.
|
750
761
|
params = Marshal.load(Marshal.dump(COMPUTE_PARAMS))
|
751
|
-
params[
|
752
|
-
params[
|
753
|
-
params[
|
762
|
+
params[:labels]['sent_label_1'] = 'value1'
|
763
|
+
params[:labels]['foo.googleapis.com/bar'] = 'value2'
|
764
|
+
params[:labels]['label3'] = 'value3'
|
754
765
|
verify_log_entries(1, params, 'structPayload') do |entry|
|
755
766
|
assert_equal 2, entry['structPayload'].size, entry
|
756
767
|
assert_equal 'test log entry 0', entry['structPayload']['message'], entry
|
@@ -1178,9 +1189,9 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
1178
1189
|
|
1179
1190
|
private
|
1180
1191
|
|
1181
|
-
def uri_for_log(
|
1182
|
-
'https://logging.googleapis.com/v1beta3/projects/' +
|
1183
|
-
'/logs/' +
|
1192
|
+
def uri_for_log(params)
|
1193
|
+
'https://logging.googleapis.com/v1beta3/projects/' + params[:project_id] +
|
1194
|
+
'/logs/' + params[:log_name] + '/entries:write'
|
1184
1195
|
end
|
1185
1196
|
|
1186
1197
|
def stub_metadata_request(metadata_path, response_body)
|
@@ -1269,9 +1280,10 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
1269
1280
|
stub_metadata_request(
|
1270
1281
|
'instance/attributes/',
|
1271
1282
|
"attribute1\ngae_backend_name\ngae_backend_version\nlast_attribute")
|
1272
|
-
stub_metadata_request('instance/attributes/gae_backend_name',
|
1283
|
+
stub_metadata_request('instance/attributes/gae_backend_name',
|
1284
|
+
MANAGED_VM_BACKEND_NAME)
|
1273
1285
|
stub_metadata_request('instance/attributes/gae_backend_version',
|
1274
|
-
|
1286
|
+
MANAGED_VM_BACKEND_VERSION)
|
1275
1287
|
end
|
1276
1288
|
|
1277
1289
|
def setup_container_metadata_stubs
|
@@ -1280,7 +1292,8 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
1280
1292
|
"attribute1\nkube-env\nlast_attribute")
|
1281
1293
|
stub_metadata_request('instance/attributes/kube-env',
|
1282
1294
|
"ENABLE_NODE_LOGGING: \"true\"\n"\
|
1283
|
-
|
1295
|
+
'INSTANCE_PREFIX: '\
|
1296
|
+
"gke-#{CONTAINER_CLUSTER_NAME}-740fdafa\n"\
|
1284
1297
|
'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
|
1285
1298
|
end
|
1286
1299
|
|
@@ -1290,9 +1303,11 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
1290
1303
|
"attribute1\nkube-env\ngcf_region\nlast_attribute")
|
1291
1304
|
stub_metadata_request('instance/attributes/kube-env',
|
1292
1305
|
"ENABLE_NODE_LOGGING: \"true\"\n"\
|
1293
|
-
|
1306
|
+
'INSTANCE_PREFIX: '\
|
1307
|
+
"gke-#{CLOUDFUNCTIONS_CLUSTER_NAME}-740fdafa\n"\
|
1294
1308
|
'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
|
1295
|
-
stub_metadata_request('instance/attributes/gcf_region',
|
1309
|
+
stub_metadata_request('instance/attributes/gcf_region',
|
1310
|
+
CLOUDFUNCTIONS_REGION)
|
1296
1311
|
end
|
1297
1312
|
|
1298
1313
|
def container_log_entry_with_metadata(log)
|
@@ -1366,9 +1381,9 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
1366
1381
|
end
|
1367
1382
|
end
|
1368
1383
|
|
1369
|
-
assert_equal params[
|
1370
|
-
assert_equal params[
|
1371
|
-
check_labels entry, batch['commonLabels'], params[
|
1384
|
+
assert_equal params[:zone], entry['metadata']['zone']
|
1385
|
+
assert_equal params[:service_name], entry['metadata']['serviceName']
|
1386
|
+
check_labels entry, batch['commonLabels'], params[:labels]
|
1372
1387
|
yield(entry) if block_given?
|
1373
1388
|
i += 1
|
1374
1389
|
assert i <= n, "Number of entries #{i} exceeds expected number #{n}"
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-google-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.16
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Todd Derr
|
@@ -9,11 +10,12 @@ authors:
|
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2016-
|
13
|
+
date: 2016-04-11 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: fluentd
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
17
19
|
requirements:
|
18
20
|
- - ~>
|
19
21
|
- !ruby/object:Gem::Version
|
@@ -21,6 +23,7 @@ dependencies:
|
|
21
23
|
type: :runtime
|
22
24
|
prerelease: false
|
23
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
24
27
|
requirements:
|
25
28
|
- - ~>
|
26
29
|
- !ruby/object:Gem::Version
|
@@ -28,6 +31,7 @@ dependencies:
|
|
28
31
|
- !ruby/object:Gem::Dependency
|
29
32
|
name: google-api-client
|
30
33
|
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
31
35
|
requirements:
|
32
36
|
- - ! '>='
|
33
37
|
- !ruby/object:Gem::Version
|
@@ -38,6 +42,7 @@ dependencies:
|
|
38
42
|
type: :runtime
|
39
43
|
prerelease: false
|
40
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
41
46
|
requirements:
|
42
47
|
- - ! '>='
|
43
48
|
- !ruby/object:Gem::Version
|
@@ -48,6 +53,7 @@ dependencies:
|
|
48
53
|
- !ruby/object:Gem::Dependency
|
49
54
|
name: googleauth
|
50
55
|
requirement: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
51
57
|
requirements:
|
52
58
|
- - ~>
|
53
59
|
- !ruby/object:Gem::Version
|
@@ -55,6 +61,7 @@ dependencies:
|
|
55
61
|
type: :runtime
|
56
62
|
prerelease: false
|
57
63
|
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
58
65
|
requirements:
|
59
66
|
- - ~>
|
60
67
|
- !ruby/object:Gem::Version
|
@@ -62,6 +69,7 @@ dependencies:
|
|
62
69
|
- !ruby/object:Gem::Dependency
|
63
70
|
name: json
|
64
71
|
requirement: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
65
73
|
requirements:
|
66
74
|
- - ~>
|
67
75
|
- !ruby/object:Gem::Version
|
@@ -69,6 +77,7 @@ dependencies:
|
|
69
77
|
type: :runtime
|
70
78
|
prerelease: false
|
71
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
72
81
|
requirements:
|
73
82
|
- - ~>
|
74
83
|
- !ruby/object:Gem::Version
|
@@ -76,6 +85,7 @@ dependencies:
|
|
76
85
|
- !ruby/object:Gem::Dependency
|
77
86
|
name: jwt
|
78
87
|
requirement: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
79
89
|
requirements:
|
80
90
|
- - <
|
81
91
|
- !ruby/object:Gem::Version
|
@@ -83,6 +93,7 @@ dependencies:
|
|
83
93
|
type: :runtime
|
84
94
|
prerelease: false
|
85
95
|
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
86
97
|
requirements:
|
87
98
|
- - <
|
88
99
|
- !ruby/object:Gem::Version
|
@@ -90,6 +101,7 @@ dependencies:
|
|
90
101
|
- !ruby/object:Gem::Dependency
|
91
102
|
name: mocha
|
92
103
|
requirement: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
93
105
|
requirements:
|
94
106
|
- - ~>
|
95
107
|
- !ruby/object:Gem::Version
|
@@ -97,6 +109,7 @@ dependencies:
|
|
97
109
|
type: :development
|
98
110
|
prerelease: false
|
99
111
|
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
100
113
|
requirements:
|
101
114
|
- - ~>
|
102
115
|
- !ruby/object:Gem::Version
|
@@ -104,6 +117,7 @@ dependencies:
|
|
104
117
|
- !ruby/object:Gem::Dependency
|
105
118
|
name: rake
|
106
119
|
requirement: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
107
121
|
requirements:
|
108
122
|
- - ~>
|
109
123
|
- !ruby/object:Gem::Version
|
@@ -111,6 +125,7 @@ dependencies:
|
|
111
125
|
type: :development
|
112
126
|
prerelease: false
|
113
127
|
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
114
129
|
requirements:
|
115
130
|
- - ~>
|
116
131
|
- !ruby/object:Gem::Version
|
@@ -118,6 +133,7 @@ dependencies:
|
|
118
133
|
- !ruby/object:Gem::Dependency
|
119
134
|
name: rubocop
|
120
135
|
requirement: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
121
137
|
requirements:
|
122
138
|
- - '='
|
123
139
|
- !ruby/object:Gem::Version
|
@@ -125,6 +141,7 @@ dependencies:
|
|
125
141
|
type: :development
|
126
142
|
prerelease: false
|
127
143
|
version_requirements: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
128
145
|
requirements:
|
129
146
|
- - '='
|
130
147
|
- !ruby/object:Gem::Version
|
@@ -132,6 +149,7 @@ dependencies:
|
|
132
149
|
- !ruby/object:Gem::Dependency
|
133
150
|
name: webmock
|
134
151
|
requirement: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
135
153
|
requirements:
|
136
154
|
- - ~>
|
137
155
|
- !ruby/object:Gem::Version
|
@@ -139,6 +157,7 @@ dependencies:
|
|
139
157
|
type: :development
|
140
158
|
prerelease: false
|
141
159
|
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
142
161
|
requirements:
|
143
162
|
- - ~>
|
144
163
|
- !ruby/object:Gem::Version
|
@@ -146,6 +165,7 @@ dependencies:
|
|
146
165
|
- !ruby/object:Gem::Dependency
|
147
166
|
name: test-unit
|
148
167
|
requirement: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
149
169
|
requirements:
|
150
170
|
- - ~>
|
151
171
|
- !ruby/object:Gem::Version
|
@@ -153,6 +173,7 @@ dependencies:
|
|
153
173
|
type: :development
|
154
174
|
prerelease: false
|
155
175
|
version_requirements: !ruby/object:Gem::Requirement
|
176
|
+
none: false
|
156
177
|
requirements:
|
157
178
|
- - ~>
|
158
179
|
- !ruby/object:Gem::Version
|
@@ -167,43 +188,44 @@ executables: []
|
|
167
188
|
extensions: []
|
168
189
|
extra_rdoc_files: []
|
169
190
|
files:
|
170
|
-
- CONTRIBUTING
|
171
|
-
- Gemfile
|
172
|
-
- Gemfile.lock
|
173
|
-
- LICENSE
|
174
|
-
- README.rdoc
|
175
|
-
- Rakefile
|
176
|
-
- fluent-plugin-google-cloud.gemspec
|
177
|
-
- lib/fluent/plugin/out_google_cloud.rb
|
178
191
|
- test/helper.rb
|
179
192
|
- test/plugin/data/c31e573fd7f62ed495c9ca3821a5a85cb036dee1-privatekey.p12
|
180
193
|
- test/plugin/data/credentials.json
|
181
194
|
- test/plugin/data/iam-credentials.json
|
182
195
|
- test/plugin/data/invalid_credentials.json
|
183
196
|
- test/plugin/test_out_google_cloud.rb
|
197
|
+
- LICENSE
|
198
|
+
- Rakefile
|
199
|
+
- fluent-plugin-google-cloud.gemspec
|
200
|
+
- lib/fluent/plugin/out_google_cloud.rb
|
201
|
+
- CONTRIBUTING
|
202
|
+
- Gemfile.lock
|
203
|
+
- Gemfile
|
204
|
+
- README.rdoc
|
184
205
|
homepage: https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud
|
185
206
|
licenses:
|
186
207
|
- Apache-2.0
|
187
|
-
metadata: {}
|
188
208
|
post_install_message:
|
189
209
|
rdoc_options: []
|
190
210
|
require_paths:
|
191
211
|
- lib
|
192
212
|
required_ruby_version: !ruby/object:Gem::Requirement
|
213
|
+
none: false
|
193
214
|
requirements:
|
194
215
|
- - ! '>='
|
195
216
|
- !ruby/object:Gem::Version
|
196
217
|
version: '0'
|
197
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
219
|
+
none: false
|
198
220
|
requirements:
|
199
221
|
- - ! '>='
|
200
222
|
- !ruby/object:Gem::Version
|
201
223
|
version: '0'
|
202
224
|
requirements: []
|
203
225
|
rubyforge_project:
|
204
|
-
rubygems_version:
|
226
|
+
rubygems_version: 1.8.23
|
205
227
|
signing_key:
|
206
|
-
specification_version:
|
228
|
+
specification_version: 3
|
207
229
|
summary: fluentd output plugin for the Google Cloud Logging API
|
208
230
|
test_files:
|
209
231
|
- test/helper.rb
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
NGQxM2IzZmRjNjdmOTQ0ZmE3ZDVjNmNkOTIzZWU4YjQxZDk4YjU2Mw==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
M2UwYzcyNzUyNzI2NTM1YTUzMDk4N2EyNzlmMzA0MGVkMWJjNjZhNw==
|
7
|
-
SHA512:
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
OGQ4ZGQ2MDljOTJkNjA0ODZhYTUwYTQ0OWZhYTIyOWU5YTE3YTA4MTM0ODQz
|
10
|
-
NWYzYjVlMjg1ZDA4MzgwMTVmZGYwODE5MzU2NGM5OGQ4NzJkNDIzNjMwMGMw
|
11
|
-
OGRhOTYyOTcyMmNjNjJiZGYyMDg3Y2UzNzM0YjY3Y2QwNDBiZWY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NGM5MTdhM2ExYjIzZGYwMGM3NjgwZjQyYWQ5NWE4NGIzNWFjZmNmMjE0OTNk
|
14
|
-
YjQ5N2EwM2ZmOGE2Njc5NGE1NDM5MTYzMjExNjQ5ZmMxMzkxNzZkNWViODMz
|
15
|
-
M2YyNGE5MzFiM2ZjZjUzOTMxZWQyZGQxNTc4M2I1M2ZmMjdiZjE=
|