google-cloud-core 1.1.0 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e44ada22e203f330c8b70e746ce7b7fe79ff7a40587f993126f18438e18bebf1
4
- data.tar.gz: a3eba190acf8259d8c9dd8c14ce8db08fa7f133a1c38c81958dac03cb74c3eeb
3
+ metadata.gz: dd3cf2a2e538cb37ffd2daae810180a7cf19dcad051f1fdce8d6b6c6dd13a566
4
+ data.tar.gz: e197ffcd7a014052eaeabba0f744ce0c3c86da7be88639bd9e91338eb122b7e4
5
5
  SHA512:
6
- metadata.gz: e230827b88d66edb003623e9955e522f5695ffd7a5d7b095bf678ae886a049014917511bfc4d79a23dfa5d16a6b64f445c985a8e57dae0298354b243a9cf3e36
7
- data.tar.gz: 4248b6744703cae1c167d6fcfc59c69a0ca99d155a17b5a7deef3137c197b7e625382d7935dab26383a64649ef692f713a933528e3a79f46406dfb94b2d6d2e4
6
+ metadata.gz: 27e11063ff53977170fa53a5559d272ac324225ee0ee9bc85f2b696b5b6f31f0719b605283eae7b73d12808a8326a97f9dd5308d89fab5b89df22dac5fdca8b3
7
+ data.tar.gz: 4ba78b2ef42de56f09660dd30c40eee1fcd7c74a6ba5c57fc126dcd05cb9af59e9087caa8f9745a44f8e332c67a6e8b16252ef8f600655ff811c74314635011b
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  Apache License
2
2
  Version 2.0, January 2004
3
- http://www.apache.org/licenses/
3
+ https://www.apache.org/licenses/
4
4
 
5
5
  TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
6
 
@@ -192,7 +192,7 @@
192
192
  you may not use this file except in compliance with the License.
193
193
  You may obtain a copy of the License at
194
194
 
195
- http://www.apache.org/licenses/LICENSE-2.0
195
+ https://www.apache.org/licenses/LICENSE-2.0
196
196
 
197
197
  Unless required by applicable law or agreed to in writing, software
198
198
  distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,10 +1,10 @@
1
- # Copyright 2015 Google Inc. All rights reserved.
1
+ # Copyright 2015 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
8
  #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
+ require "google/cloud/config"
16
17
  require "google/cloud/core/version"
17
18
 
18
19
  ##
@@ -23,10 +24,14 @@ require "google/cloud/core/version"
23
24
  # that allow you to create anything from simple websites to complex
24
25
  # applications.
25
26
  #
26
- # The goal of google-cloud is to provide a API that is familiar and comfortable
27
- # to Rubyists. Authentication is handled by providing project and credential
28
- # information, or if you are running on Google Compute Engine this configuration
29
- # is taken care of for you.
27
+ # The goal of google-cloud is to provide an API that is comfortable to
28
+ # Rubyists. Your authentication credentials are detected automatically in
29
+ # Google Cloud Platform environments such as Google Compute Engine, Google
30
+ # App Engine and Google Kubernetes Engine. In other environments you can
31
+ # configure authentication easily, either directly in your code or via
32
+ # environment variables. Read more about the options for connecting in the
33
+ # [Authentication
34
+ # Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
30
35
  #
31
36
  # You can learn more about various options for connection on the [Authentication
32
37
  # Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
@@ -67,9 +72,51 @@ module Google
67
72
  gcloud.extend Google::Cloud
68
73
  gcloud
69
74
  end
75
+
76
+ ##
77
+ # Configure the default parameter for Google::Cloud. The values defined on
78
+ # this top level will be shared across all Google::Cloud libraries, which
79
+ # may also add fields to this object or add sub configuration options under
80
+ # this object.
81
+ #
82
+ # Possible configuration parameters:
83
+ #
84
+ # * `project_id`: The Google Cloud Project ID. Automatically discovered
85
+ # when running from GCP environments.
86
+ # * `credentials`: The service account JSON file path. Automatically
87
+ # discovered when running from GCP environments.
88
+ #
89
+ # @return [Google::Cloud::Config] The top-level configuration object for
90
+ # Google::Cloud libraries.
91
+ #
92
+ def self.configure
93
+ @config ||= Config.create
94
+
95
+ yield @config if block_given?
96
+
97
+ @config
98
+ end
70
99
  end
71
100
  end
72
101
 
102
+ # Set the default top-level configuration
103
+ Google::Cloud.configure do |config|
104
+ default_project = Google::Cloud::Config.deferred do
105
+ ENV["GOOGLE_CLOUD_PROJECT"] || ENV["GCLOUD_PROJECT"]
106
+ end
107
+ default_creds = Google::Cloud::Config.deferred do
108
+ Google::Cloud::Config.credentials_from_env \
109
+ "GOOGLE_CLOUD_CREDENTIALS", "GOOGLE_CLOUD_CREDENTIALS_JSON",
110
+ "GOOGLE_CLOUD_KEYFILE", "GOOGLE_CLOUD_KEYFILE_JSON",
111
+ "GCLOUD_KEYFILE", "GCLOUD_KEYFILE_JSON"
112
+ end
113
+
114
+ config.add_field! :project_id, default_project, match: String, allow_nil: true
115
+ config.add_alias! :project, :project_id
116
+ config.add_field! :credentials, default_creds, match: Object
117
+ config.add_alias! :keyfile, :credentials
118
+ end
119
+
73
120
  # Auto-load all Google Cloud service gems.
74
121
  Gem.find_files("google-cloud-*.rb").each do |google_cloud_service|
75
122
  require google_cloud_service
@@ -0,0 +1,607 @@
1
+ # Copyright 2018 Google LLC
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
+ # https://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
+
16
+ module Google
17
+ module Cloud
18
+ ##
19
+ # Configuration mechanism for Google Cloud libraries. A Config object
20
+ # contains a list of predefined keys, some of which are values and others
21
+ # of which are subconfigurations, i.e. categories. Field access is
22
+ # generally validated to ensure that the field is defined, and when a
23
+ # a value is set, it is validated for the correct type. Warnings are
24
+ # printed when a validation fails.
25
+ #
26
+ # You generally access fields and subconfigs by calling accessor methods.
27
+ # Methods meant for "administration" such as adding options, are named
28
+ # with a trailing "!" or "?" so they don't pollute the method namespace.
29
+ # It is also possible to access a field using the `[]` operator.
30
+ #
31
+ # Note that config objects inherit from `BasicObject`. This means it does
32
+ # not define many methods you might expect to find in most Ruby objects.
33
+ # For example, `to_s`, `inspect`, `is_a?`, `instance_variable_get`, and so
34
+ # forth.
35
+ #
36
+ # @example
37
+ # require "google/cloud/config"
38
+ #
39
+ # config = Google::Cloud::Config.create do |c|
40
+ # c.add_field! :opt1, 10
41
+ # c.add_field! :opt2, :one, enum: [:one, :two, :three]
42
+ # c.add_field! :opt3, "hi", match: [String, Symbol]
43
+ # c.add_field! :opt4, "hi", match: /^[a-z]+$/, allow_nil: true
44
+ # c.add_config! :sub do |c2|
45
+ # c2.add_field! :opt5, false
46
+ # end
47
+ # end
48
+ #
49
+ # config.opt1 #=> 10
50
+ # config.opt1 = 20 #=> 20
51
+ # config.opt1 #=> 20
52
+ # config.opt1 = "hi" #=> "hi" (but prints a warning)
53
+ # config.opt1 = nil #=> nil (but prints a warning)
54
+ #
55
+ # config.opt2 #=> :one
56
+ # config.opt2 = :two #=> :two
57
+ # config.opt2 #=> :two
58
+ # config.opt2 = :four #=> :four (but prints a warning)
59
+ #
60
+ # config.opt3 #=> "hi"
61
+ # config.opt3 = "hiho" #=> "hiho"
62
+ # config.opt3 #=> "hiho"
63
+ # config.opt3 = "HI" #=> "HI" (but prints a warning)
64
+ #
65
+ # config.opt4 #=> "yo"
66
+ # config.opt4 = :yo #=> :yo (Strings and Symbols allowed)
67
+ # config.opt4 #=> :yo
68
+ # config.opt4 = 3.14 #=> 3.14 (but prints a warning)
69
+ # config.opt4 = nil #=> nil (no warning: nil allowed)
70
+ #
71
+ # config.sub #=> <Google::Cloud::Config>
72
+ #
73
+ # config.sub.opt5 #=> false
74
+ # config.sub.opt5 = true #=> true (true and false allowed)
75
+ # config.sub.opt5 #=> true
76
+ # config.sub.opt5 = nil #=> nil (but prints a warning)
77
+ #
78
+ # config.opt9 = "hi" #=> "hi" (warning about unknown key)
79
+ # config.opt9 #=> "hi" (no warning: key now known)
80
+ # config.sub.opt9 #=> nil (warning about unknown key)
81
+ #
82
+ class Config < BasicObject
83
+ ##
84
+ # Constructs a Config object. If a block is given, yields `self` to the
85
+ # block, which makes it convenient to initialize the structure by making
86
+ # calls to `add_field!` and `add_config!`.
87
+ #
88
+ # @param [boolean] show_warnings Whether to print warnings when a
89
+ # validation fails. Defaults to `true`.
90
+ # @return [Config] The constructed Config object.
91
+ #
92
+ def self.create show_warnings: true
93
+ config = new [], show_warnings: show_warnings
94
+ yield config if block_given?
95
+ config
96
+ end
97
+
98
+ ##
99
+ # Determines if the given object is a config. Useful because Config
100
+ # does not define the `is_a?` method.
101
+ #
102
+ # @return [boolean]
103
+ #
104
+ def self.config? obj
105
+ Config.send :===, obj
106
+ end
107
+
108
+ ##
109
+ # Internal constructor. Generally you should not call `new` directly,
110
+ # but instead use the `Config.create` method. The initializer is used
111
+ # directly by a few older clients that expect a legacy interface.
112
+ #
113
+ # @private
114
+ #
115
+ def initialize legacy_categories = {}, opts = {}
116
+ @show_warnings = opts.fetch :show_warnings, false
117
+ @values = {}
118
+ @defaults = {}
119
+ @validators = {}
120
+ add_options legacy_categories
121
+ end
122
+
123
+ ##
124
+ # Legacy method of adding subconfigs. This is used by older versions of
125
+ # the stackdriver client libraries but should not be used in new code.
126
+ #
127
+ # @deprecated
128
+ # @private
129
+ #
130
+ def add_options legacy_categories
131
+ [legacy_categories].flatten(1).each do |sub_key|
132
+ case sub_key
133
+ when ::Symbol
134
+ add_config! sub_key, Config.new
135
+ when ::Hash
136
+ sub_key.each do |k, v|
137
+ add_config! k, Config.new(v)
138
+ end
139
+ else
140
+ raise ArgumentError "Category must be a Symbol or Hash"
141
+ end
142
+ end
143
+ end
144
+
145
+ ##
146
+ # Add a value field to this configuration.
147
+ #
148
+ # You must provide a key, which becomes the field name in this config.
149
+ # Field names may comprise only letters, numerals, and underscores, and
150
+ # must begin with a letter. This will create accessor methods for the
151
+ # new configuration key.
152
+ #
153
+ # You may pass an initial value (which defaults to nil if not provided).
154
+ #
155
+ # You may also specify how values are validated. Validation is defined
156
+ # as follows:
157
+ #
158
+ # * If you provide a block or a `:validator` option, it is used as the
159
+ # validator. A proposed value is passed to the proc, which should
160
+ # return `true` or `false` to indicate whether the value is valid.
161
+ # * If you provide a `:match` option, it is compared to the proposed
162
+ # value using the `===` operator. You may, for example, provide a
163
+ # class, a regular expression, or a range. If you pass an array,
164
+ # the value is accepted if _any_ of the elements match.
165
+ # * If you provide an `:enum` option, it should be an `Enumerable`.
166
+ # A proposed value is valid if it is included.
167
+ # * Otherwise if you do not provide any of the above options, then a
168
+ # default validation strategy is inferred from the initial value:
169
+ # * If the initial is `true` or `false`, then either boolean value
170
+ # is considered valid. This is the same as `enum: [true, false]`.
171
+ # * If the initial is `nil`, then any object is considered valid.
172
+ # * Otherwise, any object of the same class as the initial value is
173
+ # considered valid. This is effectively the same as
174
+ # `match: initial.class`.
175
+ # * You may also provide the `:allow_nil` option, which, if set to
176
+ # true, alters any of the above validators to allow `nil` values.
177
+ #
178
+ # In many cases, you may find that the default validation behavior
179
+ # (interpreted from the initial value) is sufficient. If you want to
180
+ # accept any value, use `match: Object`.
181
+ #
182
+ # @param [String, Symbol] key The name of the option
183
+ # @param [Object] initial Initial value (defaults to nil)
184
+ # @param [Hash] opts Validation options
185
+ #
186
+ # @return [Config] self for chaining
187
+ #
188
+ def add_field! key, initial = nil, opts = {}, &block
189
+ key = validate_new_key! key
190
+ opts[:validator] = block if block
191
+ validator = resolve_validator! initial, opts
192
+ validate_value! key, validator, initial
193
+ @values[key] = initial
194
+ @defaults[key] = initial
195
+ @validators[key] = validator
196
+ self
197
+ end
198
+
199
+ ##
200
+ # Add a subconfiguration field to this configuration.
201
+ #
202
+ # You must provide a key, which becomes the method name that you use to
203
+ # navigate to the subconfig. Names may comprise only letters, numerals,
204
+ # and underscores, and must begin with a letter.
205
+ #
206
+ # If you provide a block, the subconfig object is passed to the block,
207
+ # so you can easily add fields to the subconfig.
208
+ #
209
+ # You may also pass in a config object that already exists. This will
210
+ # "attach" that configuration in this location.
211
+ #
212
+ # @param [String, Symbol] key The name of the subconfig
213
+ # @param [Config] config A config object to attach here. If not provided,
214
+ # creates a new config.
215
+ #
216
+ # @return [Config] self for chaining
217
+ #
218
+ def add_config! key, config = nil, &block
219
+ key = validate_new_key! key
220
+ if config.nil?
221
+ config = Config.create(&block)
222
+ elsif block
223
+ yield config
224
+ end
225
+ @values[key] = config
226
+ @defaults[key] = config
227
+ @validators[key] = SUBCONFIG
228
+ self
229
+ end
230
+
231
+ ##
232
+ # Cause a key to be an alias of another key. The two keys will refer to
233
+ # the same field.
234
+ #
235
+ def add_alias! key, to_key
236
+ key = validate_new_key! key
237
+ @values.delete key
238
+ @defaults.delete key
239
+ @validators[key] = to_key.to_sym
240
+ self
241
+ end
242
+
243
+ ##
244
+ # Restore the original default value of the given key.
245
+ # If the key is omitted, restore the original defaults for all keys,
246
+ # and all keys of subconfigs, recursively.
247
+ #
248
+ # @param [Symbol, nil] key The key to reset. If omitted or `nil`,
249
+ # recursively reset all fields and subconfigs.
250
+ #
251
+ def reset! key = nil
252
+ if key.nil?
253
+ @values.each_key { |k| reset! k }
254
+ else
255
+ key = key.to_sym
256
+ if @defaults.key? key
257
+ @values[key] = @defaults[key]
258
+ @values[key].reset! if @validators[key] == SUBCONFIG
259
+ elsif @values.key? key
260
+ warn! "Key #{key.inspect} has not been added, but has a value." \
261
+ " Removing the value."
262
+ @values.delete key
263
+ else
264
+ warn! "Key #{key.inspect} does not exist. Nothing to reset."
265
+ end
266
+ end
267
+ self
268
+ end
269
+
270
+ ##
271
+ # Remove the given key from the configuration, deleting any validation
272
+ # and value. If the key is omitted, delete all keys. If the key is an
273
+ # alias, deletes the alias but leaves the original.
274
+ #
275
+ # @param [Symbol, nil] key The key to delete. If omitted or `nil`,
276
+ # delete all fields and subconfigs.
277
+ #
278
+ def delete! key = nil
279
+ if key.nil?
280
+ @values.clear
281
+ @defaults.clear
282
+ @validators.clear
283
+ else
284
+ @values.delete key
285
+ @defaults.delete key
286
+ @validators.delete key
287
+ end
288
+ self
289
+ end
290
+
291
+ ##
292
+ # Assign an option with the given name to the given value.
293
+ #
294
+ # @param [Symbol, String] key The option name
295
+ # @param [Object] value The new option value
296
+ #
297
+ def []= key, value
298
+ key = resolve_key! key
299
+ validate_value! key, @validators[key], value
300
+ @values[key] = value
301
+ end
302
+
303
+ ##
304
+ # Get the option or subconfig with the given name.
305
+ #
306
+ # @param [Symbol, String] key The option or subconfig name
307
+ # @return [Object] The option value or subconfig object
308
+ #
309
+ def [] key
310
+ key = resolve_key! key
311
+ unless @validators.key? key
312
+ warn! "Key #{key.inspect} does not exist. Returning nil."
313
+ end
314
+ value = @values[key]
315
+ value = value.call if Config::DeferredValue === value
316
+ value
317
+ end
318
+
319
+ ##
320
+ # Check if the given key has been set in this object. Returns true if the
321
+ # key has been added as a normal field, subconfig, or alias, or if it has
322
+ # not been added explicitly but still has a value.
323
+ #
324
+ # @param [Symbol] key The key to check for.
325
+ # @return [boolean]
326
+ #
327
+ def value_set? key
328
+ @values.key? resolve_key! key
329
+ end
330
+ alias option? value_set?
331
+
332
+ ##
333
+ # Check if the given key has been explicitly added as a field name.
334
+ #
335
+ # @param [Symbol] key The key to check for.
336
+ # @return [boolean]
337
+ #
338
+ def field? key
339
+ @validators[key.to_sym].is_a? ::Proc
340
+ end
341
+
342
+ ##
343
+ # Check if the given key has been explicitly added as a subconfig name.
344
+ #
345
+ # @param [Symbol] key The key to check for.
346
+ # @return [boolean]
347
+ #
348
+ def subconfig? key
349
+ @validators[key.to_sym] == SUBCONFIG
350
+ end
351
+
352
+ ##
353
+ # Check if the given key has been explicitly added as an alias.
354
+ # If so, return the target, otherwise return nil.
355
+ #
356
+ # @param [Symbol] key The key to check for.
357
+ # @return [Symbol,nil] The alias target, or nil if not an alias.
358
+ #
359
+ def alias? key
360
+ target = @validators[key.to_sym]
361
+ target.is_a?(::Symbol) ? target : nil
362
+ end
363
+
364
+ ##
365
+ # Return a list of explicitly added field names.
366
+ #
367
+ # @return [Array<Symbol>] a list of field names as symbols.
368
+ #
369
+ def fields!
370
+ @validators.keys.find_all { |key| @validators[key].is_a? ::Proc }
371
+ end
372
+
373
+ ##
374
+ # Return a list of explicitly added subconfig names.
375
+ #
376
+ # @return [Array<Symbol>] a list of subconfig names as symbols.
377
+ #
378
+ def subconfigs!
379
+ @validators.keys.find_all { |key| @validators[key] == SUBCONFIG }
380
+ end
381
+
382
+ ##
383
+ # Return a list of alias names.
384
+ #
385
+ # @return [Array<Symbol>] a list of alias names as symbols.
386
+ #
387
+ def aliases!
388
+ @validators.keys.find_all { |key| @validators[key].is_a? ::Symbol }
389
+ end
390
+
391
+ ##
392
+ # Returns a string representation of this configuration state, including
393
+ # subconfigs. Only explicitly added fields and subconfigs are included.
394
+ #
395
+ # @return [String]
396
+ #
397
+ def to_s!
398
+ elems = @validators.keys.map do |k|
399
+ v = @values[k]
400
+ vstr = Config.config?(v) ? v.to_s! : value.inspect
401
+ " #{k}=#{vstr}"
402
+ end
403
+ "<Config:#{elems.join}>"
404
+ end
405
+
406
+ ##
407
+ # Returns a nested hash representation of this configuration state,
408
+ # including subconfigs. Only explicitly added fields and subconfigs are
409
+ # included.
410
+ #
411
+ # @return [Hash]
412
+ #
413
+ def to_h!
414
+ h = {}
415
+ @validators.each_key do |k|
416
+ v = @values[k]
417
+ h[k] = Config.config?(v) ? v.to_h! : v.inspect
418
+ end
419
+ h
420
+ end
421
+
422
+ ##
423
+ # Search the given environment variable names for valid credential data
424
+ # that can be passed to `Google::Auth::Credentials.new`.
425
+ # If a variable contains a valid file path, returns that path as a string.
426
+ # If a variable contains valid JSON, returns the parsed JSON as a hash.
427
+ # If no variables contain valid data, returns nil.
428
+ # @private
429
+ #
430
+ def self.credentials_from_env *vars
431
+ vars.each do |var|
432
+ data = ::ENV[var]
433
+ next unless data
434
+ str = data.strip
435
+ return str if ::File.file? str
436
+ json = begin
437
+ ::JSON.parse str
438
+ rescue ::StandardError
439
+ nil
440
+ end
441
+ return json if json.is_a? ::Hash
442
+ end
443
+ nil
444
+ end
445
+
446
+ ##
447
+ # @private
448
+ # Create a configuration value that will be invoked when retrieved.
449
+ #
450
+ def self.deferred &block
451
+ DeferredValue.new(&block)
452
+ end
453
+
454
+ ##
455
+ # @private
456
+ # Dynamic methods accessed as keys.
457
+ #
458
+ def method_missing name, *args
459
+ name_str = name.to_s
460
+ super unless name_str =~ /^[a-zA-Z]\w*=?$/
461
+ if name_str.chomp! "="
462
+ self[name_str] = args.first
463
+ else
464
+ self[name]
465
+ end
466
+ end
467
+
468
+ ##
469
+ # @private
470
+ # Dynamic methods accessed as keys.
471
+ #
472
+ def respond_to_missing? name, include_private
473
+ return true if value_set? name.to_s.chomp("=")
474
+ super
475
+ end
476
+
477
+ ##
478
+ # @private
479
+ # Implement standard nil check
480
+ #
481
+ # @return [false]
482
+ #
483
+ def nil?
484
+ false
485
+ end
486
+
487
+ private
488
+
489
+ ##
490
+ # @private A validator that allows all values
491
+ #
492
+ OPEN_VALIDATOR = ::Proc.new { true }
493
+
494
+ ##
495
+ # @private a list of key names that are technically illegal because
496
+ # they clash with method names.
497
+ #
498
+ ILLEGAL_KEYS = %i[
499
+ add_options
500
+ initialize
501
+ instance_eval
502
+ instance_exec
503
+ method_missing
504
+ singleton_method_added
505
+ singleton_method_removed
506
+ singleton_method_undefined
507
+ ].freeze
508
+
509
+ ##
510
+ # @private sentinel indicating a subconfig in the validators hash
511
+ #
512
+ SUBCONFIG = ::Object.new
513
+
514
+ def resolve_key! key
515
+ key = key.to_sym
516
+ alias_target = @validators[key]
517
+ alias_target.is_a?(::Symbol) ? alias_target : key
518
+ end
519
+
520
+ def validate_new_key! key
521
+ key_str = key.to_s
522
+ key = key.to_sym
523
+ if key_str !~ /^[a-zA-Z]\w*$/ || ILLEGAL_KEYS.include?(key)
524
+ warn! "Illegal key name: #{key_str.inspect}. Method dispatch will" \
525
+ " not work for this key."
526
+ end
527
+ if @validators.key? key
528
+ warn! "Key #{key.inspect} already exists. It will be replaced."
529
+ end
530
+ key
531
+ end
532
+
533
+ def resolve_validator! initial, opts
534
+ allow_nil = initial.nil? || opts[:allow_nil]
535
+ if opts.key? :validator
536
+ build_proc_validator! opts[:validator], allow_nil
537
+ elsif opts.key? :match
538
+ build_match_validator! opts[:match], allow_nil
539
+ elsif opts.key? :enum
540
+ build_enum_validator! opts[:enum], allow_nil
541
+ elsif [true, false].include? initial
542
+ build_enum_validator! [true, false], allow_nil
543
+ elsif initial.nil?
544
+ OPEN_VALIDATOR
545
+ else
546
+ klass = Config.config?(initial) ? Config : initial.class
547
+ build_match_validator! klass, allow_nil
548
+ end
549
+ end
550
+
551
+ def build_match_validator! matches, allow_nil
552
+ matches = ::Kernel.Array(matches)
553
+ matches += [nil] if allow_nil && !matches.include?(nil)
554
+ ->(val) { matches.any? { |m| m.send :===, val } }
555
+ end
556
+
557
+ def build_enum_validator! allowed, allow_nil
558
+ allowed = ::Kernel.Array(allowed)
559
+ allowed += [nil] if allow_nil && !allowed.include?(nil)
560
+ ->(val) { allowed.include? val }
561
+ end
562
+
563
+ def build_proc_validator! proc, allow_nil
564
+ ->(val) { proc.call(val) || (allow_nil && val.nil?) }
565
+ end
566
+
567
+ def validate_value! key, validator, value
568
+ value = value.call if Config::DeferredValue === value
569
+ case validator
570
+ when ::Proc
571
+ unless validator.call value
572
+ warn! "Invalid value #{value.inspect} for key #{key.inspect}." \
573
+ " Setting anyway."
574
+ end
575
+ when Config
576
+ if value != validator
577
+ warn! "Key #{key.inspect} refers to a subconfig and shouldn't" \
578
+ " be changed. Setting anyway."
579
+ end
580
+ else
581
+ warn! "Key #{key.inspect} has not been added. Setting anyway."
582
+ end
583
+ end
584
+
585
+ def warn! msg
586
+ return unless @show_warnings
587
+ location = ::Kernel.caller_locations.find do |s|
588
+ !s.to_s.include? "/google/cloud/config.rb:"
589
+ end
590
+ ::Kernel.warn "#{msg} at #{location}"
591
+ end
592
+
593
+ ##
594
+ # @private
595
+ #
596
+ class DeferredValue
597
+ def initialize &block
598
+ @callback = block
599
+ end
600
+
601
+ def call
602
+ @callback.call
603
+ end
604
+ end
605
+ end
606
+ end
607
+ end
@@ -1,10 +1,10 @@
1
- # Copyright 2016 Google Inc. All rights reserved.
1
+ # Copyright 2016 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
8
  #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Core
19
- VERSION = "1.1.0"
19
+ VERSION = "1.2.0".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -1,10 +1,10 @@
1
- # Copyright 2014 Google Inc. All rights reserved.
1
+ # Copyright 2014 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
8
  #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
@@ -33,8 +33,8 @@ module Google
33
33
  TOKEN_CREDENTIAL_URI = "https://accounts.google.com/o/oauth2/token"
34
34
  AUDIENCE = "https://accounts.google.com/o/oauth2/token"
35
35
  SCOPE = []
36
- PATH_ENV_VARS = %w(GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
37
- JSON_ENV_VARS = %w(GOOGLE_CLOUD_KEYFILE_JSON GCLOUD_KEYFILE_JSON)
36
+ PATH_ENV_VARS = %w[GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE]
37
+ JSON_ENV_VARS = %w[GOOGLE_CLOUD_KEYFILE_JSON GCLOUD_KEYFILE_JSON]
38
38
  DEFAULT_PATHS = ["~/.config/gcloud/application_default_credentials.json"]
39
39
 
40
40
  attr_accessor :client
@@ -72,10 +72,9 @@ module Google
72
72
  path = ->(p) { ::File.file? p }
73
73
 
74
74
  # First try to find keyfile file from environment variables.
75
- self::PATH_ENV_VARS.map(&env).compact.select(&path)
76
- .each do |file|
77
- return new file, scope: scope
78
- end
75
+ self::PATH_ENV_VARS.map(&env).compact.select(&path).each do |file|
76
+ return new file, scope: scope
77
+ end
79
78
  # Second try to find keyfile json from environment variables.
80
79
  self::JSON_ENV_VARS.map(&json).compact.each do |hash|
81
80
  return new hash, scope: scope
@@ -95,14 +94,14 @@ module Google
95
94
  ##
96
95
  # Verify that the keyfile argument is provided.
97
96
  def verify_keyfile_provided! keyfile
98
- fail "You must provide a keyfile to connect with." if keyfile.nil?
97
+ raise "You must provide a keyfile to connect with." if keyfile.nil?
99
98
  end
100
99
 
101
100
  ##
102
101
  # Verify that the keyfile argument is a file.
103
102
  def verify_keyfile_exists! keyfile
104
103
  exists = ::File.file? keyfile
105
- fail "The keyfile '#{keyfile}' is not a valid file." unless exists
104
+ raise "The keyfile '#{keyfile}' is not a valid file." unless exists
106
105
  end
107
106
 
108
107
  ##
@@ -1,10 +1,10 @@
1
- # Copyright 2015 Google Inc. All rights reserved.
1
+ # Copyright 2015 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
6
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
8
  #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
@@ -146,18 +146,21 @@ module Google
146
146
  def self.grpc_error_class_for grpc_error_code
147
147
  # The gRPC status code 0 is for a successful response.
148
148
  # So there is no error subclass for a 0 status code, use current class.
149
- [self, CanceledError, UnknownError, InvalidArgumentError,
150
- DeadlineExceededError, NotFoundError, AlreadyExistsError,
151
- PermissionDeniedError, ResourceExhaustedError, FailedPreconditionError,
152
- AbortedError, OutOfRangeError, UnimplementedError, InternalError,
153
- UnavailableError, DataLossError, UnauthenticatedError
149
+ [
150
+ self, CanceledError, UnknownError, InvalidArgumentError,
151
+ DeadlineExceededError, NotFoundError, AlreadyExistsError,
152
+ PermissionDeniedError, ResourceExhaustedError,
153
+ FailedPreconditionError, AbortedError, OutOfRangeError,
154
+ UnimplementedError, InternalError, UnavailableError, DataLossError,
155
+ UnauthenticatedError
154
156
  ][grpc_error_code] || self
155
157
  end
156
158
 
157
159
  # @private Identify the subclass for a Google API Client error
158
160
  def self.gapi_error_class_for http_status_code
159
161
  # The http status codes mapped to their error classes.
160
- { 400 => InvalidArgumentError, # FailedPreconditionError/OutOfRangeError
162
+ {
163
+ 400 => InvalidArgumentError, # FailedPreconditionError/OutOfRangeError
161
164
  401 => UnauthenticatedError,
162
165
  403 => PermissionDeniedError,
163
166
  404 => NotFoundError,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Moore
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-11-14 00:00:00.000000000 Z
12
+ date: 2018-02-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-cloud-env
@@ -99,16 +99,16 @@ dependencies:
99
99
  name: rubocop
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "<="
102
+ - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: 0.35.1
104
+ version: 0.50.0
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "<="
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: 0.35.1
111
+ version: 0.50.0
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: simplecov
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -163,6 +163,7 @@ files:
163
163
  - LICENSE
164
164
  - README.md
165
165
  - lib/google/cloud.rb
166
+ - lib/google/cloud/config.rb
166
167
  - lib/google/cloud/core/version.rb
167
168
  - lib/google/cloud/credentials.rb
168
169
  - lib/google/cloud/errors.rb
@@ -186,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
187
  version: '0'
187
188
  requirements: []
188
189
  rubyforge_project:
189
- rubygems_version: 2.7.2
190
+ rubygems_version: 2.7.6
190
191
  signing_key:
191
192
  specification_version: 4
192
193
  summary: Internal shared library for google-cloud-ruby