fluent-plugin-google-cloud 0.8.4 → 0.9.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
  SHA256:
3
- metadata.gz: eb0b416356143a700e7abeb68072df8423e44183cc370dea070c591f47ab5d2d
4
- data.tar.gz: 36764f53fea714492770ac0d93152c5ad96a53c0ac58f79a645bccb8bdb20269
3
+ metadata.gz: f873763395e9eff23e78cf7d645e42277be2b12e022334954b97d5a8b1a96f73
4
+ data.tar.gz: 26a2146530ef1bce151f6ee4d4fe0625f7dfec6019108cb96f68390c1aef6288
5
5
  SHA512:
6
- metadata.gz: 53ee7847c4b048a4d11b812f012587744be59f7abf3dbc039762d786306a740450267b762f1d4a7f0b1e317e6d6c12b31a9a59324c126ec144cae4a19959e312
7
- data.tar.gz: 221ad4d3d2955d81c484aeaf3dcbcaadd83bd04271df4b3ddc9b491e000feb9efb08f831912bd60dce3883902d60f855f8a921aff2188f34e0024d41daa5640f
6
+ metadata.gz: '051824ee94d4a2de635afe4b28e91475e422767d66407d2040e9d315f6a822d7cdaece7014ab2e6ab7211817b948f51fc385779182258d180e1a5492974f0ac1'
7
+ data.tar.gz: 8d373bb349402697ab45a3ec11186b0970fadb8ac66ddf25190bf68c4a6ccf0939b627ceb151922d4d8871e361b20ba3fadcfb254e7422c9d0f10b0ade7cb68b
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-google-cloud (0.8.4)
4
+ fluent-plugin-google-cloud (0.9.1)
5
5
  fluentd (= 1.7.4)
6
6
  google-api-client (= 0.30.8)
7
7
  google-cloud-logging (= 1.6.6)
8
- google-protobuf (= 3.9.0)
8
+ google-protobuf (= 3.12.2)
9
9
  googleapis-common-protos (= 1.3.9)
10
10
  googleauth (= 0.9.0)
11
- grpc (= 1.22.0)
11
+ grpc (= 1.30.2)
12
12
  json (= 2.2.0)
13
13
  opencensus (= 0.5.0)
14
14
  opencensus-stackdriver (= 0.3.2)
@@ -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.0)
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)
@@ -29,7 +29,7 @@ GEM
29
29
  tins (~> 1.6)
30
30
  crack (0.4.3)
31
31
  safe_yaml (~> 1.0.0)
32
- declarative (0.0.10)
32
+ declarative (0.0.20)
33
33
  declarative-option (0.1.0)
34
34
  dig_rb (1.0.1)
35
35
  docile (1.3.2)
@@ -46,6 +46,12 @@ GEM
46
46
  tzinfo (~> 2.0)
47
47
  tzinfo-data (~> 1.0)
48
48
  yajl-ruby (~> 1.0)
49
+ gapic-common (0.3.1)
50
+ google-protobuf (~> 3.12, >= 3.12.2)
51
+ googleapis-common-protos (>= 1.3.9, < 2.0)
52
+ googleapis-common-protos-types (>= 1.0.4, < 2.0)
53
+ googleauth (~> 0.9)
54
+ grpc (~> 1.25)
49
55
  google-api-client (0.30.8)
50
56
  addressable (~> 2.5, >= 2.5.1)
51
57
  googleauth (>= 0.5, < 0.10.0)
@@ -57,36 +63,44 @@ GEM
57
63
  google-cloud-core (1.5.0)
58
64
  google-cloud-env (~> 1.0)
59
65
  google-cloud-errors (~> 1.0)
60
- google-cloud-env (1.3.1)
66
+ google-cloud-env (1.3.3)
61
67
  faraday (>= 0.17.3, < 2.0)
62
- google-cloud-errors (1.0.0)
68
+ google-cloud-errors (1.0.1)
63
69
  google-cloud-logging (1.6.6)
64
70
  concurrent-ruby (~> 1.1)
65
71
  google-cloud-core (~> 1.2)
66
72
  google-gax (~> 1.7)
67
73
  googleapis-common-protos-types (>= 1.0.2)
68
74
  stackdriver-core (~> 1.3)
69
- google-cloud-monitoring (0.32.0)
70
- google-gax (~> 1.7)
71
- googleapis-common-protos-types (>= 1.0.2)
72
- google-cloud-trace (0.35.0)
75
+ google-cloud-monitoring (0.38.0)
76
+ google-gax (~> 1.8)
77
+ googleapis-common-protos (>= 1.3.9, < 2.0)
78
+ googleapis-common-protos-types (>= 1.0.4, < 2.0)
79
+ google-cloud-trace (0.40.0)
73
80
  concurrent-ruby (~> 1.1)
74
- google-cloud-core (~> 1.2)
75
- google-gax (~> 1.7)
81
+ google-cloud-core (~> 1.5)
82
+ google-cloud-trace-v1 (~> 0.0)
83
+ google-cloud-trace-v2 (~> 0.0)
76
84
  stackdriver-core (~> 1.3)
77
- google-gax (1.7.1)
78
- google-protobuf (~> 3.2)
79
- googleapis-common-protos (>= 1.3.5, < 2.0)
80
- googleauth (>= 0.6.2, < 0.10.0)
81
- grpc (>= 1.7.2, < 2.0)
85
+ google-cloud-trace-v1 (0.1.0)
86
+ gapic-common (~> 0.3)
87
+ google-cloud-errors (~> 1.0)
88
+ google-cloud-trace-v2 (0.1.0)
89
+ gapic-common (~> 0.3)
90
+ google-cloud-errors (~> 1.0)
91
+ google-gax (1.8.1)
92
+ google-protobuf (~> 3.9)
93
+ googleapis-common-protos (>= 1.3.9, < 2.0)
94
+ googleauth (~> 0.9)
95
+ grpc (~> 1.24)
82
96
  rly (~> 0.2.3)
83
- google-protobuf (3.9.0)
97
+ google-protobuf (3.12.2)
84
98
  googleapis-common-protos (1.3.9)
85
99
  google-protobuf (~> 3.0)
86
100
  googleapis-common-protos-types (~> 1.0)
87
101
  grpc (~> 1.0)
88
- googleapis-common-protos-types (1.0.4)
89
- google-protobuf (~> 3.0)
102
+ googleapis-common-protos-types (1.0.5)
103
+ google-protobuf (~> 3.11)
90
104
  googleauth (0.9.0)
91
105
  faraday (~> 0.12)
92
106
  jwt (>= 1.4, < 3.0)
@@ -94,8 +108,8 @@ GEM
94
108
  multi_json (~> 1.11)
95
109
  os (>= 0.9, < 2.0)
96
110
  signet (~> 0.7)
97
- grpc (1.22.0)
98
- google-protobuf (~> 3.8)
111
+ grpc (1.30.2)
112
+ google-protobuf (~> 3.12)
99
113
  googleapis-common-protos-types (~> 1.0)
100
114
  hashdiff (1.0.1)
101
115
  http_parser.rb (0.6.0)
@@ -108,7 +122,7 @@ GEM
108
122
  mocha (1.9.0)
109
123
  metaclass (~> 0.0.1)
110
124
  msgpack (1.3.3)
111
- multi_json (1.14.1)
125
+ multi_json (1.15.0)
112
126
  multipart-post (2.1.1)
113
127
  opencensus (0.5.0)
114
128
  opencensus-stackdriver (0.3.2)
@@ -116,14 +130,14 @@ GEM
116
130
  google-cloud-monitoring (~> 0.32)
117
131
  google-cloud-trace (~> 0.35)
118
132
  opencensus (~> 0.5)
119
- os (1.0.1)
120
- parser (2.7.0.5)
121
- ast (~> 2.4.0)
122
- power_assert (1.1.7)
133
+ os (1.1.0)
134
+ parser (2.7.1.4)
135
+ ast (~> 2.4.1)
136
+ power_assert (1.2.0)
123
137
  powerpack (0.1.2)
124
138
  prometheus-client (0.9.0)
125
139
  quantile (~> 0.2.1)
126
- public_suffix (4.0.3)
140
+ public_suffix (4.0.5)
127
141
  quantile (0.2.1)
128
142
  rainbow (2.2.2)
129
143
  rake
@@ -145,7 +159,7 @@ GEM
145
159
  serverengine (2.2.1)
146
160
  sigdump (~> 0.2.2)
147
161
  sigdump (0.2.4)
148
- signet (0.13.2)
162
+ signet (0.14.0)
149
163
  addressable (~> 2.3)
150
164
  faraday (>= 0.17.3, < 2.0)
151
165
  jwt (>= 1.5, < 3.0)
@@ -157,18 +171,18 @@ GEM
157
171
  simplecov-html (0.10.2)
158
172
  stackdriver-core (1.4.0)
159
173
  google-cloud-core (~> 1.2)
160
- strptime (0.2.3)
174
+ strptime (0.2.4)
161
175
  sync (0.5.0)
162
176
  term-ansicolor (1.7.1)
163
177
  tins (~> 1.0)
164
178
  test-unit (3.3.3)
165
179
  power_assert
166
180
  thor (1.0.1)
167
- tins (1.24.1)
181
+ tins (1.25.0)
168
182
  sync
169
- tzinfo (2.0.1)
183
+ tzinfo (2.0.2)
170
184
  concurrent-ruby (~> 1.0)
171
- tzinfo-data (1.2019.3)
185
+ tzinfo-data (1.2020.1)
172
186
  tzinfo (>= 1.0.0)
173
187
  uber (0.1.0)
174
188
  unicode-display_width (1.7.0)
@@ -192,4 +206,4 @@ DEPENDENCIES
192
206
  webmock (= 3.6.2)
193
207
 
194
208
  BUNDLED WITH
195
- 2.1.1
209
+ 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.4'
13
+ gem.version = '0.9.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')
@@ -24,8 +24,8 @@ eos
24
24
  gem.add_runtime_dependency 'googleauth', '0.9.0'
25
25
  gem.add_runtime_dependency 'google-api-client', '0.30.8'
26
26
  gem.add_runtime_dependency 'google-cloud-logging', '1.6.6'
27
- gem.add_runtime_dependency 'google-protobuf', '3.9.0'
28
- gem.add_runtime_dependency 'grpc', '1.22.0'
27
+ gem.add_runtime_dependency 'google-protobuf', '3.12.2'
28
+ gem.add_runtime_dependency 'grpc', '1.30.2'
29
29
  gem.add_runtime_dependency 'json', '2.2.0'
30
30
  gem.add_runtime_dependency 'opencensus', '0.5.0'
31
31
  gem.add_runtime_dependency 'opencensus-stackdriver', '0.3.2'
@@ -0,0 +1,386 @@
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
+ # Create a monitored resource from type and labels.
223
+ def create_monitored_resource(type, labels)
224
+ Google::Apis::LoggingV2::MonitoredResource.new(
225
+ type: type, labels: labels.to_h)
226
+ end
227
+
228
+ # Retrieve monitored resource via the legacy way.
229
+ #
230
+ # Note: This is just a failover plan if we fail to get metadata from
231
+ # Metadata Agent. Thus it should be equivalent to what Metadata Agent
232
+ # returns.
233
+ def determine_agent_level_monitored_resource_via_legacy(
234
+ platform, subservice_name, detect_subservice, vm_id, zone)
235
+ resource_type = determine_agent_level_monitored_resource_type(
236
+ platform, subservice_name, detect_subservice)
237
+ create_monitored_resource(
238
+ resource_type,
239
+ determine_agent_level_monitored_resource_labels(
240
+ platform, resource_type, vm_id, zone))
241
+ end
242
+
243
+ # Determine agent level monitored resource type.
244
+ def determine_agent_level_monitored_resource_type(
245
+ platform, subservice_name, detect_subservice)
246
+ case platform
247
+ when Platform::OTHER
248
+ # Unknown platform will be defaulted to GCE instance.
249
+ return COMPUTE_CONSTANTS[:resource_type]
250
+
251
+ when Platform::EC2
252
+ return EC2_CONSTANTS[:resource_type]
253
+
254
+ when Platform::GCE
255
+ # Resource types determined by subservice_name config.
256
+ return SUBSERVICE_MAP[subservice_name] if subservice_name
257
+
258
+ # Resource types determined by detect_subservice config.
259
+ if detect_subservice
260
+ begin
261
+ attributes = fetch_gce_metadata(platform,
262
+ 'instance/attributes/').split.to_set
263
+ SUBSERVICE_METADATA_ATTRIBUTES.each do |resource_type, expected|
264
+ return resource_type if attributes.superset?(expected)
265
+ end
266
+ rescue StandardError => e
267
+ @log.error 'Failed to detect subservice: ', error: e
268
+ end
269
+ end
270
+
271
+ # GCE instance.
272
+ return COMPUTE_CONSTANTS[:resource_type]
273
+ end
274
+ end
275
+
276
+ # Determine agent level monitored resource labels based on the resource
277
+ # type. Each resource type has its own labels that need to be filled in.
278
+ def determine_agent_level_monitored_resource_labels(
279
+ platform, type, vm_id, zone)
280
+ case type
281
+ # GAE app.
282
+ when APPENGINE_CONSTANTS[:resource_type]
283
+ return {
284
+ 'module_id' =>
285
+ fetch_gce_metadata(platform,
286
+ 'instance/attributes/gae_backend_name'),
287
+ 'version_id' =>
288
+ fetch_gce_metadata(platform,
289
+ 'instance/attributes/gae_backend_version')
290
+ }
291
+
292
+ # GCE.
293
+ when COMPUTE_CONSTANTS[:resource_type]
294
+ raise "Cannot construct a #{type} resource without vm_id and zone" \
295
+ unless vm_id && zone
296
+ return {
297
+ 'instance_id' => vm_id,
298
+ 'zone' => zone
299
+ }
300
+
301
+ # GKE container.
302
+ when GKE_CONSTANTS[:resource_type]
303
+ raise "Cannot construct a #{type} resource without vm_id and zone" \
304
+ unless vm_id && zone
305
+ return {
306
+ 'instance_id' => vm_id,
307
+ 'zone' => zone,
308
+ 'cluster_name' =>
309
+ fetch_gce_metadata(platform, 'instance/attributes/cluster-name')
310
+ }
311
+
312
+ # Cloud Dataproc.
313
+ when DATAPROC_CONSTANTS[:resource_type]
314
+ return {
315
+ 'cluster_uuid' =>
316
+ fetch_gce_metadata(platform,
317
+ 'instance/attributes/dataproc-cluster-uuid'),
318
+ 'cluster_name' =>
319
+ fetch_gce_metadata(platform,
320
+ 'instance/attributes/dataproc-cluster-name'),
321
+ 'region' =>
322
+ fetch_gce_metadata(platform,
323
+ 'instance/attributes/dataproc-region')
324
+ }
325
+
326
+ # EC2.
327
+ when EC2_CONSTANTS[:resource_type]
328
+ raise "Cannot construct a #{type} resource without vm_id and zone" \
329
+ unless vm_id && zone
330
+ labels = {
331
+ 'instance_id' => vm_id,
332
+ 'region' => zone
333
+ }
334
+ labels['aws_account'] = ec2_metadata(platform)['accountId'] if
335
+ ec2_metadata(platform).key?('accountId')
336
+ return labels
337
+ end
338
+
339
+ {}
340
+ rescue StandardError => e
341
+ if [Platform::GCE, Platform::EC2].include?(platform)
342
+ @log.error "Failed to set monitored resource labels for #{type}: ",
343
+ error: e
344
+ end
345
+ {}
346
+ end
347
+
348
+ # TODO: This functionality should eventually be available in another
349
+ # library, but implement it ourselves for now.
350
+ module CredentialsInfo
351
+ # Determine the project ID from the credentials, if possible.
352
+ # Returns the project ID (as a string) on success, or nil on failure.
353
+ def self.project_id
354
+ creds = Google::Auth.get_application_default(LOGGING_SCOPE)
355
+ if creds.respond_to?(:project_id)
356
+ return creds.project_id if creds.project_id
357
+ end
358
+ if creds.issuer
359
+ id = extract_project_id(creds.issuer)
360
+ return id unless id.nil?
361
+ end
362
+ if creds.client_id
363
+ id = extract_project_id(creds.client_id)
364
+ return id unless id.nil?
365
+ end
366
+ nil
367
+ end
368
+
369
+ # Extracts the project id (either name or number) from str and returns
370
+ # it (as a string) on success, or nil on failure.
371
+ #
372
+ # Recognizes IAM format (account@project-name.iam.gserviceaccount.com)
373
+ # as well as the legacy format with a project number at the front of the
374
+ # string, terminated by a dash (-) which is not part of the ID, i.e.:
375
+ # <PROJECT_ID>-<OTHER_PARTS>.apps.googleusercontent.com
376
+ def self.extract_project_id(str)
377
+ [/^.*@(?<project_id>.+)\.iam\.gserviceaccount\.com/,
378
+ /^(?<project_id>\d+)-/].each do |exp|
379
+ match_data = exp.match(str)
380
+ return match_data['project_id'] unless match_data.nil?
381
+ end
382
+ nil
383
+ end
384
+ end
385
+ end
386
+ end