fluent-plugin-google-cloud 0.8.2 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +14 -14
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/common.rb +381 -0
- data/lib/fluent/plugin/filter_analyze_config.rb +306 -0
- data/lib/fluent/plugin/out_google_cloud.rb +29 -358
- data/test/plugin/asserts.rb +75 -0
- data/test/plugin/base_test.rb +3 -60
- data/test/plugin/constants.rb +9 -1
- data/test/plugin/data/google-fluentd-baseline.conf +24 -0
- data/test/plugin/data/google-fluentd-custom.conf +40 -0
- data/test/plugin/test_filter_analyze_config.rb +187 -0
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 851c496e93becdfb6a735f9c71aceecfdeccfff14519ce8311bb3dd42c7ed382
|
4
|
+
data.tar.gz: d893b865df5a2b10bac43c65381abe1b95e27333ff77ac45c6cb988c2f446036
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f840e9c06e995be5dd4abd0dcd9d04042c6d78507896fc842ab2b1fb8cb82eac4535fdb6259656cc703e99955e074e64c1ec0292c31d77647cbc95d54e7b919
|
7
|
+
data.tar.gz: c1573f562d3691a83b8b3dd2b8e8a0ed1585edac5f67df6179bc8c62af4a3728ce97b90be8827008718921069806eb6e0d2e81fd5c7f6de4c6603a1c2738774e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.8.
|
4
|
+
fluent-plugin-google-cloud (0.8.7)
|
5
5
|
fluentd (= 1.7.4)
|
6
6
|
google-api-client (= 0.30.8)
|
7
7
|
google-cloud-logging (= 1.6.6)
|
@@ -18,7 +18,7 @@ GEM
|
|
18
18
|
specs:
|
19
19
|
addressable (2.7.0)
|
20
20
|
public_suffix (>= 2.0.2, < 5.0)
|
21
|
-
ast (2.4.
|
21
|
+
ast (2.4.1)
|
22
22
|
concurrent-ruby (1.1.6)
|
23
23
|
cool.io (1.6.0)
|
24
24
|
coveralls (0.8.23)
|
@@ -57,9 +57,9 @@ GEM
|
|
57
57
|
google-cloud-core (1.5.0)
|
58
58
|
google-cloud-env (~> 1.0)
|
59
59
|
google-cloud-errors (~> 1.0)
|
60
|
-
google-cloud-env (1.3.
|
60
|
+
google-cloud-env (1.3.2)
|
61
61
|
faraday (>= 0.17.3, < 2.0)
|
62
|
-
google-cloud-errors (1.0.
|
62
|
+
google-cloud-errors (1.0.1)
|
63
63
|
google-cloud-logging (1.6.6)
|
64
64
|
concurrent-ruby (~> 1.1)
|
65
65
|
google-cloud-core (~> 1.2)
|
@@ -116,14 +116,14 @@ GEM
|
|
116
116
|
google-cloud-monitoring (~> 0.32)
|
117
117
|
google-cloud-trace (~> 0.35)
|
118
118
|
opencensus (~> 0.5)
|
119
|
-
os (1.0
|
120
|
-
parser (2.7.
|
119
|
+
os (1.1.0)
|
120
|
+
parser (2.7.1.3)
|
121
121
|
ast (~> 2.4.0)
|
122
|
-
power_assert (1.
|
122
|
+
power_assert (1.2.0)
|
123
123
|
powerpack (0.1.2)
|
124
124
|
prometheus-client (0.9.0)
|
125
125
|
quantile (~> 0.2.1)
|
126
|
-
public_suffix (4.0.
|
126
|
+
public_suffix (4.0.5)
|
127
127
|
quantile (0.2.1)
|
128
128
|
rainbow (2.2.2)
|
129
129
|
rake
|
@@ -145,7 +145,7 @@ GEM
|
|
145
145
|
serverengine (2.2.1)
|
146
146
|
sigdump (~> 0.2.2)
|
147
147
|
sigdump (0.2.4)
|
148
|
-
signet (0.
|
148
|
+
signet (0.14.0)
|
149
149
|
addressable (~> 2.3)
|
150
150
|
faraday (>= 0.17.3, < 2.0)
|
151
151
|
jwt (>= 1.5, < 3.0)
|
@@ -157,18 +157,18 @@ GEM
|
|
157
157
|
simplecov-html (0.10.2)
|
158
158
|
stackdriver-core (1.4.0)
|
159
159
|
google-cloud-core (~> 1.2)
|
160
|
-
strptime (0.2.
|
160
|
+
strptime (0.2.4)
|
161
161
|
sync (0.5.0)
|
162
162
|
term-ansicolor (1.7.1)
|
163
163
|
tins (~> 1.0)
|
164
164
|
test-unit (3.3.3)
|
165
165
|
power_assert
|
166
166
|
thor (1.0.1)
|
167
|
-
tins (1.
|
167
|
+
tins (1.25.0)
|
168
168
|
sync
|
169
|
-
tzinfo (2.0.
|
169
|
+
tzinfo (2.0.2)
|
170
170
|
concurrent-ruby (~> 1.0)
|
171
|
-
tzinfo-data (1.
|
171
|
+
tzinfo-data (1.2020.1)
|
172
172
|
tzinfo (>= 1.0.0)
|
173
173
|
uber (0.1.0)
|
174
174
|
unicode-display_width (1.7.0)
|
@@ -192,4 +192,4 @@ DEPENDENCIES
|
|
192
192
|
webmock (= 3.6.2)
|
193
193
|
|
194
194
|
BUNDLED WITH
|
195
|
-
2.1.
|
195
|
+
2.1.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.8.
|
13
|
+
gem.version = '0.8.7'
|
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')
|
@@ -0,0 +1,381 @@
|
|
1
|
+
# Copyright 2020 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Common
|
16
|
+
# Constants for service names, resource types and etc.
|
17
|
+
module ServiceConstants
|
18
|
+
APPENGINE_CONSTANTS = {
|
19
|
+
service: 'appengine.googleapis.com',
|
20
|
+
resource_type: 'gae_app',
|
21
|
+
metadata_attributes: %w(gae_backend_name gae_backend_version)
|
22
|
+
}.freeze
|
23
|
+
COMPUTE_CONSTANTS = {
|
24
|
+
service: 'compute.googleapis.com',
|
25
|
+
resource_type: 'gce_instance'
|
26
|
+
}.freeze
|
27
|
+
GKE_CONSTANTS = {
|
28
|
+
service: 'container.googleapis.com',
|
29
|
+
resource_type: 'gke_container',
|
30
|
+
extra_resource_labels: %w(namespace_id pod_id container_name),
|
31
|
+
extra_common_labels: %w(namespace_name pod_name),
|
32
|
+
metadata_attributes: %w(cluster-name cluster-location),
|
33
|
+
stream_severity_map: {
|
34
|
+
'stdout' => 'INFO',
|
35
|
+
'stderr' => 'ERROR'
|
36
|
+
}
|
37
|
+
}.freeze
|
38
|
+
K8S_CONTAINER_CONSTANTS = {
|
39
|
+
resource_type: 'k8s_container'
|
40
|
+
}.freeze
|
41
|
+
K8S_POD_CONSTANTS = {
|
42
|
+
resource_type: 'k8s_pod'
|
43
|
+
}.freeze
|
44
|
+
K8S_NODE_CONSTANTS = {
|
45
|
+
resource_type: 'k8s_node'
|
46
|
+
}.freeze
|
47
|
+
DATAFLOW_CONSTANTS = {
|
48
|
+
service: 'dataflow.googleapis.com',
|
49
|
+
resource_type: 'dataflow_step',
|
50
|
+
extra_resource_labels: %w(region job_name job_id step_id)
|
51
|
+
}.freeze
|
52
|
+
DATAPROC_CONSTANTS = {
|
53
|
+
service: 'cluster.dataproc.googleapis.com',
|
54
|
+
resource_type: 'cloud_dataproc_cluster',
|
55
|
+
metadata_attributes: %w(dataproc-cluster-uuid dataproc-cluster-name)
|
56
|
+
}.freeze
|
57
|
+
EC2_CONSTANTS = {
|
58
|
+
service: 'ec2.amazonaws.com',
|
59
|
+
resource_type: 'aws_ec2_instance'
|
60
|
+
}.freeze
|
61
|
+
ML_CONSTANTS = {
|
62
|
+
service: 'ml.googleapis.com',
|
63
|
+
resource_type: 'ml_job',
|
64
|
+
extra_resource_labels: %w(job_id task_name)
|
65
|
+
}.freeze
|
66
|
+
|
67
|
+
# The map between a subservice name and a resource type.
|
68
|
+
SUBSERVICE_MAP =
|
69
|
+
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAFLOW_CONSTANTS,
|
70
|
+
DATAPROC_CONSTANTS, ML_CONSTANTS]
|
71
|
+
.map { |consts| [consts[:service], consts[:resource_type]] }.to_h
|
72
|
+
# Default back to GCE if invalid value is detected.
|
73
|
+
SUBSERVICE_MAP.default = COMPUTE_CONSTANTS[:resource_type]
|
74
|
+
SUBSERVICE_MAP.freeze
|
75
|
+
|
76
|
+
# The map between a resource type and expected subservice attributes.
|
77
|
+
SUBSERVICE_METADATA_ATTRIBUTES =
|
78
|
+
[APPENGINE_CONSTANTS, GKE_CONSTANTS, DATAPROC_CONSTANTS].map do |consts|
|
79
|
+
[consts[:resource_type], consts[:metadata_attributes].to_set]
|
80
|
+
end.to_h.freeze
|
81
|
+
end
|
82
|
+
|
83
|
+
# Name of the the Google cloud logging write scope.
|
84
|
+
LOGGING_SCOPE = 'https://www.googleapis.com/auth/logging.write'.freeze
|
85
|
+
|
86
|
+
# Address of the metadata service.
|
87
|
+
METADATA_SERVICE_ADDR = '169.254.169.254'.freeze
|
88
|
+
|
89
|
+
# "enum" of Platform values
|
90
|
+
module Platform
|
91
|
+
OTHER = 0 # Other/unkown platform
|
92
|
+
GCE = 1 # Google Compute Engine
|
93
|
+
EC2 = 2 # Amazon EC2
|
94
|
+
end
|
95
|
+
|
96
|
+
# Utilities for managing the resource used when writing to the
|
97
|
+
# Google API.
|
98
|
+
class Utils
|
99
|
+
include Common::ServiceConstants
|
100
|
+
|
101
|
+
def initialize(log)
|
102
|
+
@log = log
|
103
|
+
end
|
104
|
+
|
105
|
+
# Determine what platform we are running on by consulting the metadata
|
106
|
+
# service (unless the user has explicitly disabled using that).
|
107
|
+
def detect_platform(use_metadata_service)
|
108
|
+
unless use_metadata_service
|
109
|
+
@log.info 'use_metadata_service is false; not detecting platform'
|
110
|
+
return Platform::OTHER
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
open('http://' + METADATA_SERVICE_ADDR, proxy: false) do |f|
|
115
|
+
if f.meta['metadata-flavor'] == 'Google'
|
116
|
+
@log.info 'Detected GCE platform'
|
117
|
+
return Platform::GCE
|
118
|
+
end
|
119
|
+
if f.meta['server'] == 'EC2ws'
|
120
|
+
@log.info 'Detected EC2 platform'
|
121
|
+
return Platform::EC2
|
122
|
+
end
|
123
|
+
end
|
124
|
+
rescue StandardError => e
|
125
|
+
@log.error 'Failed to access metadata service: ', error: e
|
126
|
+
end
|
127
|
+
|
128
|
+
@log.info 'Unable to determine platform'
|
129
|
+
Platform::OTHER
|
130
|
+
end
|
131
|
+
|
132
|
+
def fetch_gce_metadata(platform, metadata_path)
|
133
|
+
raise "Called fetch_gce_metadata with platform=#{platform}" unless
|
134
|
+
platform == Platform::GCE
|
135
|
+
# See https://cloud.google.com/compute/docs/metadata
|
136
|
+
open('http://' + METADATA_SERVICE_ADDR + '/computeMetadata/v1/' +
|
137
|
+
metadata_path, 'Metadata-Flavor' => 'Google', :proxy => false,
|
138
|
+
&:read)
|
139
|
+
end
|
140
|
+
|
141
|
+
# EC2 Metadata server returns everything in one call. Store it after the
|
142
|
+
# first fetch to avoid making multiple calls.
|
143
|
+
def ec2_metadata(platform)
|
144
|
+
raise "Called ec2_metadata with platform=#{platform}" unless
|
145
|
+
platform == Platform::EC2
|
146
|
+
unless @ec2_metadata
|
147
|
+
# See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
|
148
|
+
open('http://' + METADATA_SERVICE_ADDR +
|
149
|
+
'/latest/dynamic/instance-identity/document', proxy: false) do |f|
|
150
|
+
contents = f.read
|
151
|
+
@ec2_metadata = JSON.parse(contents)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
@ec2_metadata
|
156
|
+
end
|
157
|
+
|
158
|
+
# Check required variables like @project_id, @vm_id, @vm_name and @zone.
|
159
|
+
def check_required_metadata_variables(platform, project_id, zone, vm_id)
|
160
|
+
missing = []
|
161
|
+
missing << 'project_id' unless project_id
|
162
|
+
if platform != Platform::OTHER
|
163
|
+
missing << 'zone' unless zone
|
164
|
+
missing << 'vm_id' unless vm_id
|
165
|
+
end
|
166
|
+
return if missing.empty?
|
167
|
+
raise Fluent::ConfigError,
|
168
|
+
"Unable to obtain metadata parameters: #{missing.join(' ')}"
|
169
|
+
end
|
170
|
+
|
171
|
+
# 1. Return the value if it is explicitly set in the config already.
|
172
|
+
# 2. If not, try to retrieve it by calling metadata server directly.
|
173
|
+
# 3. If still not set, try to obtain it from the credentials.
|
174
|
+
def get_project_id(platform, project_id)
|
175
|
+
project_id ||= CredentialsInfo.project_id
|
176
|
+
project_id ||= fetch_gce_metadata(platform, 'project/project-id') if
|
177
|
+
platform == Platform::GCE
|
178
|
+
project_id
|
179
|
+
end
|
180
|
+
|
181
|
+
# 1. Return the value if it is explicitly set in the config already.
|
182
|
+
# 2. If not, try to retrieve it by calling metadata servers directly.
|
183
|
+
def get_vm_id(platform, vm_id)
|
184
|
+
vm_id ||= fetch_gce_metadata(platform, 'instance/id') if
|
185
|
+
platform == Platform::GCE
|
186
|
+
vm_id ||= ec2_metadata(platform)['instanceId'] if
|
187
|
+
platform == Platform::EC2
|
188
|
+
vm_id
|
189
|
+
rescue StandardError => e
|
190
|
+
@log.error 'Failed to obtain vm_id: ', error: e
|
191
|
+
end
|
192
|
+
|
193
|
+
# 1. Return the value if it is explicitly set in the config already.
|
194
|
+
# 2. If not, try to retrieve it locally.
|
195
|
+
def get_vm_name(vm_name)
|
196
|
+
vm_name ||= Socket.gethostname
|
197
|
+
vm_name
|
198
|
+
rescue StandardError => e
|
199
|
+
@log.error 'Failed to obtain vm name: ', error: e
|
200
|
+
end
|
201
|
+
|
202
|
+
# 1. Return the value if it is explicitly set in the config already.
|
203
|
+
# 2. If not, try to retrieve it locally.
|
204
|
+
def get_location(platform, zone, use_aws_availability_zone)
|
205
|
+
# Response format: "projects/<number>/zones/<zone>"
|
206
|
+
zone ||= fetch_gce_metadata(platform,
|
207
|
+
'instance/zone').rpartition('/')[2] if
|
208
|
+
platform == Platform::GCE
|
209
|
+
aws_location_key = if use_aws_availability_zone
|
210
|
+
'availabilityZone'
|
211
|
+
else
|
212
|
+
'region'
|
213
|
+
end
|
214
|
+
zone ||= 'aws:' + ec2_metadata(platform)[aws_location_key] if
|
215
|
+
platform == Platform::EC2 &&
|
216
|
+
ec2_metadata(platform).key?(aws_location_key)
|
217
|
+
zone
|
218
|
+
rescue StandardError => e
|
219
|
+
@log.error 'Failed to obtain location: ', error: e
|
220
|
+
end
|
221
|
+
|
222
|
+
# Retrieve monitored resource via the legacy way.
|
223
|
+
#
|
224
|
+
# Note: This is just a failover plan if we fail to get metadata from
|
225
|
+
# Metadata Agent. Thus it should be equivalent to what Metadata Agent
|
226
|
+
# returns.
|
227
|
+
def determine_agent_level_monitored_resource_via_legacy(
|
228
|
+
platform, subservice_name, detect_subservice, vm_id, zone)
|
229
|
+
resource = Google::Apis::LoggingV2::MonitoredResource.new(
|
230
|
+
labels: {})
|
231
|
+
resource.type = determine_agent_level_monitored_resource_type(
|
232
|
+
platform, subservice_name, detect_subservice)
|
233
|
+
resource.labels = determine_agent_level_monitored_resource_labels(
|
234
|
+
platform, resource.type, vm_id, zone)
|
235
|
+
resource
|
236
|
+
end
|
237
|
+
|
238
|
+
# Determine agent level monitored resource type.
|
239
|
+
def determine_agent_level_monitored_resource_type(
|
240
|
+
platform, subservice_name, detect_subservice)
|
241
|
+
case platform
|
242
|
+
when Platform::OTHER
|
243
|
+
# Unknown platform will be defaulted to GCE instance.
|
244
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
245
|
+
|
246
|
+
when Platform::EC2
|
247
|
+
return EC2_CONSTANTS[:resource_type]
|
248
|
+
|
249
|
+
when Platform::GCE
|
250
|
+
# Resource types determined by subservice_name config.
|
251
|
+
return SUBSERVICE_MAP[subservice_name] if subservice_name
|
252
|
+
|
253
|
+
# Resource types determined by detect_subservice config.
|
254
|
+
if detect_subservice
|
255
|
+
begin
|
256
|
+
attributes = fetch_gce_metadata(platform,
|
257
|
+
'instance/attributes/').split.to_set
|
258
|
+
SUBSERVICE_METADATA_ATTRIBUTES.each do |resource_type, expected|
|
259
|
+
return resource_type if attributes.superset?(expected)
|
260
|
+
end
|
261
|
+
rescue StandardError => e
|
262
|
+
@log.error 'Failed to detect subservice: ', error: e
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# GCE instance.
|
267
|
+
return COMPUTE_CONSTANTS[:resource_type]
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Determine agent level monitored resource labels based on the resource
|
272
|
+
# type. Each resource type has its own labels that need to be filled in.
|
273
|
+
def determine_agent_level_monitored_resource_labels(
|
274
|
+
platform, type, vm_id, zone)
|
275
|
+
case type
|
276
|
+
# GAE app.
|
277
|
+
when APPENGINE_CONSTANTS[:resource_type]
|
278
|
+
return {
|
279
|
+
'module_id' =>
|
280
|
+
fetch_gce_metadata(platform,
|
281
|
+
'instance/attributes/gae_backend_name'),
|
282
|
+
'version_id' =>
|
283
|
+
fetch_gce_metadata(platform,
|
284
|
+
'instance/attributes/gae_backend_version')
|
285
|
+
}
|
286
|
+
|
287
|
+
# GCE.
|
288
|
+
when COMPUTE_CONSTANTS[:resource_type]
|
289
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
290
|
+
unless vm_id && zone
|
291
|
+
return {
|
292
|
+
'instance_id' => vm_id,
|
293
|
+
'zone' => zone
|
294
|
+
}
|
295
|
+
|
296
|
+
# GKE container.
|
297
|
+
when GKE_CONSTANTS[:resource_type]
|
298
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
299
|
+
unless vm_id && zone
|
300
|
+
return {
|
301
|
+
'instance_id' => vm_id,
|
302
|
+
'zone' => zone,
|
303
|
+
'cluster_name' =>
|
304
|
+
fetch_gce_metadata(platform, 'instance/attributes/cluster-name')
|
305
|
+
}
|
306
|
+
|
307
|
+
# Cloud Dataproc.
|
308
|
+
when DATAPROC_CONSTANTS[:resource_type]
|
309
|
+
return {
|
310
|
+
'cluster_uuid' =>
|
311
|
+
fetch_gce_metadata(platform,
|
312
|
+
'instance/attributes/dataproc-cluster-uuid'),
|
313
|
+
'cluster_name' =>
|
314
|
+
fetch_gce_metadata(platform,
|
315
|
+
'instance/attributes/dataproc-cluster-name'),
|
316
|
+
'region' =>
|
317
|
+
fetch_gce_metadata(platform,
|
318
|
+
'instance/attributes/dataproc-region')
|
319
|
+
}
|
320
|
+
|
321
|
+
# EC2.
|
322
|
+
when EC2_CONSTANTS[:resource_type]
|
323
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
324
|
+
unless vm_id && zone
|
325
|
+
labels = {
|
326
|
+
'instance_id' => vm_id,
|
327
|
+
'region' => zone
|
328
|
+
}
|
329
|
+
labels['aws_account'] = ec2_metadata(platform)['accountId'] if
|
330
|
+
ec2_metadata(platform).key?('accountId')
|
331
|
+
return labels
|
332
|
+
end
|
333
|
+
|
334
|
+
{}
|
335
|
+
rescue StandardError => e
|
336
|
+
if [Platform::GCE, Platform::EC2].include?(platform)
|
337
|
+
@log.error "Failed to set monitored resource labels for #{type}: ",
|
338
|
+
error: e
|
339
|
+
end
|
340
|
+
{}
|
341
|
+
end
|
342
|
+
|
343
|
+
# TODO: This functionality should eventually be available in another
|
344
|
+
# library, but implement it ourselves for now.
|
345
|
+
module CredentialsInfo
|
346
|
+
# Determine the project ID from the credentials, if possible.
|
347
|
+
# Returns the project ID (as a string) on success, or nil on failure.
|
348
|
+
def self.project_id
|
349
|
+
creds = Google::Auth.get_application_default(LOGGING_SCOPE)
|
350
|
+
if creds.respond_to?(:project_id)
|
351
|
+
return creds.project_id if creds.project_id
|
352
|
+
end
|
353
|
+
if creds.issuer
|
354
|
+
id = extract_project_id(creds.issuer)
|
355
|
+
return id unless id.nil?
|
356
|
+
end
|
357
|
+
if creds.client_id
|
358
|
+
id = extract_project_id(creds.client_id)
|
359
|
+
return id unless id.nil?
|
360
|
+
end
|
361
|
+
nil
|
362
|
+
end
|
363
|
+
|
364
|
+
# Extracts the project id (either name or number) from str and returns
|
365
|
+
# it (as a string) on success, or nil on failure.
|
366
|
+
#
|
367
|
+
# Recognizes IAM format (account@project-name.iam.gserviceaccount.com)
|
368
|
+
# as well as the legacy format with a project number at the front of the
|
369
|
+
# string, terminated by a dash (-) which is not part of the ID, i.e.:
|
370
|
+
# <PROJECT_ID>-<OTHER_PARTS>.apps.googleusercontent.com
|
371
|
+
def self.extract_project_id(str)
|
372
|
+
[/^.*@(?<project_id>.+)\.iam\.gserviceaccount\.com/,
|
373
|
+
/^(?<project_id>\d+)-/].each do |exp|
|
374
|
+
match_data = exp.match(str)
|
375
|
+
return match_data['project_id'] unless match_data.nil?
|
376
|
+
end
|
377
|
+
nil
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|