google-cloud-core 0.20.1
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 +7 -0
- data/lib/google/cloud.rb +75 -0
- data/lib/google/cloud/core/backoff.rb +89 -0
- data/lib/google/cloud/core/gce.rb +60 -0
- data/lib/google/cloud/core/grpc_backoff.rb +89 -0
- data/lib/google/cloud/core/grpc_utils.rb +91 -0
- data/lib/google/cloud/core/version.rb +22 -0
- data/lib/google/cloud/credentials.rb +132 -0
- data/lib/google/cloud/errors.rb +208 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 29d08e42cbb895f42a47e1eedcd28c7b15dd77fa
|
4
|
+
data.tar.gz: f5808aba10c3cf10fd76786e774b878f7ee9925f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9e6c3fcc7b93a69cf29254ccef9c5c7b404743cdbc6e05ea1d08ace3a2c79c884c97e9d536e9e99d5259ca441d5e2d72c1df2af1af7df8557ea6cda3ca96b2c2
|
7
|
+
data.tar.gz: ef9af1e66e014e1f92922e6c869798a27294cb11f0b7d2402780603a80a3a1a327ad883c4ec9f4ab63ced13af05740cf105f466c75eb6b5e7ca395e1c4ebc6cf
|
data/lib/google/cloud.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright 2015 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
|
+
|
16
|
+
require "google/cloud/core/version"
|
17
|
+
|
18
|
+
##
|
19
|
+
# # Google Cloud
|
20
|
+
#
|
21
|
+
# The google-cloud library is the official library for interacting with Google
|
22
|
+
# Cloud Platform. Google Cloud Platform is a set of modular cloud-based services
|
23
|
+
# that allow you to create anything from simple websites to complex
|
24
|
+
# applications.
|
25
|
+
#
|
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.
|
30
|
+
#
|
31
|
+
# You can learn more about various options for connection on the [Authentication
|
32
|
+
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
|
33
|
+
#
|
34
|
+
module Google
|
35
|
+
module Cloud
|
36
|
+
##
|
37
|
+
# Creates a new object for connecting to Google Cloud.
|
38
|
+
#
|
39
|
+
# For more information on connecting to Google Cloud see the [Authentication
|
40
|
+
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
|
41
|
+
#
|
42
|
+
# @param [String] project Project identifier for the Pub/Sub service you are
|
43
|
+
# connecting to.
|
44
|
+
# @param [String, Hash] keyfile Keyfile downloaded from Google Cloud. If
|
45
|
+
# file path the file must be readable.
|
46
|
+
# @param [Integer] retries Number of times to retry requests on server
|
47
|
+
# error. The default value is `3`. Optional.
|
48
|
+
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
49
|
+
#
|
50
|
+
# @return [Google::Cloud]
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# require "google/cloud"
|
54
|
+
#
|
55
|
+
# gcloud = Google::Cloud.new
|
56
|
+
# datastore = gcloud.datastore
|
57
|
+
# pubsub = gcloud.pubsub
|
58
|
+
# storage = gcloud.storage
|
59
|
+
#
|
60
|
+
def self.new project = nil, keyfile = nil, retries: nil, timeout: nil
|
61
|
+
gcloud = Object.new
|
62
|
+
gcloud.instance_variable_set "@project", project
|
63
|
+
gcloud.instance_variable_set "@keyfile", keyfile
|
64
|
+
gcloud.instance_variable_set "@retries", retries
|
65
|
+
gcloud.instance_variable_set "@timeout", timeout
|
66
|
+
gcloud.extend Google::Cloud
|
67
|
+
gcloud
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Auto-load all Google Cloud service gems.
|
73
|
+
Gem.find_files("google-cloud-*.rb").each do |google_cloud_service|
|
74
|
+
require google_cloud_service
|
75
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Copyright 2014 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
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Core
|
19
|
+
##
|
20
|
+
# @private
|
21
|
+
# Backoff allows users to control how Google API calls are retried.
|
22
|
+
# If an API call fails the response will be checked to see if the
|
23
|
+
# call can be retried. If the response matches the criteria, then it
|
24
|
+
# will be retried with an incremental backoff. This means that an
|
25
|
+
# increasing delay will be added between each retried call. The first
|
26
|
+
# retry will be delayed one second, the second retry will be delayed
|
27
|
+
# two seconds, and so on.
|
28
|
+
class GrpcBackoff
|
29
|
+
class << self
|
30
|
+
##
|
31
|
+
# The number of times a retriable API call should be retried.
|
32
|
+
#
|
33
|
+
# The default value is `3`.
|
34
|
+
attr_reader :retries
|
35
|
+
def retries= new_retries
|
36
|
+
@retries = new_retries
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# The GRPC Status Codes that should be retried.
|
41
|
+
#
|
42
|
+
# The default values are `14`.
|
43
|
+
attr_accessor :grpc_codes
|
44
|
+
|
45
|
+
##
|
46
|
+
# The code to run when a backoff is handled.
|
47
|
+
# This must be a Proc and must take the number of
|
48
|
+
# retries as an argument.
|
49
|
+
#
|
50
|
+
# Note: This method is undocumented and may change.
|
51
|
+
attr_accessor :backoff # :nodoc:
|
52
|
+
end
|
53
|
+
# Set the default values
|
54
|
+
self.retries = 3
|
55
|
+
self.grpc_codes = [14]
|
56
|
+
self.backoff = ->(retries) { sleep retries.to_i }
|
57
|
+
|
58
|
+
##
|
59
|
+
# @private
|
60
|
+
# Creates a new GrpcBackoff object to catch common errors when calling
|
61
|
+
# the Google API and handle the error by retrying the call.
|
62
|
+
#
|
63
|
+
# Google::Cloud::Core::GrpcBackoff.new(options).execute do
|
64
|
+
# datastore.lookup lookup_req
|
65
|
+
# end
|
66
|
+
def initialize options = {}
|
67
|
+
@retries = (options[:retries] || GrpcBackoff.retries).to_i
|
68
|
+
@grpc_codes = (options[:grpc_codes] || GrpcBackoff.grpc_codes).to_a
|
69
|
+
@backoff = options[:backoff] || GrpcBackoff.backoff
|
70
|
+
end
|
71
|
+
|
72
|
+
# @private
|
73
|
+
def execute
|
74
|
+
current_retries = 0
|
75
|
+
loop do
|
76
|
+
begin
|
77
|
+
return yield
|
78
|
+
rescue GRPC::BadStatus => e
|
79
|
+
raise e unless @grpc_codes.include?(e.code) &&
|
80
|
+
(current_retries < @retries)
|
81
|
+
current_retries += 1
|
82
|
+
@backoff.call current_retries
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright 2015 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
|
+
|
16
|
+
require "faraday"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Core
|
21
|
+
##
|
22
|
+
# @private
|
23
|
+
# Represents the Google Compute Engine environment.
|
24
|
+
module GCE
|
25
|
+
CHECK_URI = "http://169.254.169.254"
|
26
|
+
PROJECT_URI = "#{CHECK_URI}/computeMetadata/v1/project/project-id"
|
27
|
+
|
28
|
+
def self.gce? options = {}
|
29
|
+
conn = options[:connection] || Faraday.default_connection
|
30
|
+
resp = conn.get CHECK_URI do |req|
|
31
|
+
req.options.timeout = 0.1
|
32
|
+
end
|
33
|
+
return false unless resp.status == 200
|
34
|
+
return false unless resp.headers.key? "Metadata-Flavor"
|
35
|
+
return resp.headers["Metadata-Flavor"] == "Google"
|
36
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.project_id options = {}
|
41
|
+
@gce ||= {}
|
42
|
+
return @gce[:project_id] if @gce.key? :project_id
|
43
|
+
conn = options[:connection] || Faraday.default_connection
|
44
|
+
conn.headers = { "Metadata-Flavor" => "Google" }
|
45
|
+
resp = conn.get PROJECT_URI do |req|
|
46
|
+
req.options.timeout = 0.1
|
47
|
+
end
|
48
|
+
if resp.status == 200
|
49
|
+
@gce[:project_id] = resp.body
|
50
|
+
else
|
51
|
+
@gce[:project_id] = nil
|
52
|
+
end
|
53
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed
|
54
|
+
@gce ||= {}
|
55
|
+
@gce[:project_id] = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Copyright 2014 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
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Core
|
19
|
+
##
|
20
|
+
# @private
|
21
|
+
# Backoff allows users to control how Google API calls are retried.
|
22
|
+
# If an API call fails the response will be checked to see if the
|
23
|
+
# call can be retried. If the response matches the criteria, then it
|
24
|
+
# will be retried with an incremental backoff. This means that an
|
25
|
+
# increasing delay will be added between each retried call. The first
|
26
|
+
# retry will be delayed one second, the second retry will be delayed
|
27
|
+
# two seconds, and so on.
|
28
|
+
class GrpcBackoff
|
29
|
+
class << self
|
30
|
+
##
|
31
|
+
# The number of times a retriable API call should be retried.
|
32
|
+
#
|
33
|
+
# The default value is `3`.
|
34
|
+
attr_reader :retries
|
35
|
+
def retries= new_retries
|
36
|
+
@retries = new_retries
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# The GRPC Status Codes that should be retried.
|
41
|
+
#
|
42
|
+
# The default values are `14`.
|
43
|
+
attr_accessor :grpc_codes
|
44
|
+
|
45
|
+
##
|
46
|
+
# The code to run when a backoff is handled.
|
47
|
+
# This must be a Proc and must take the number of
|
48
|
+
# retries as an argument.
|
49
|
+
#
|
50
|
+
# Note: This method is undocumented and may change.
|
51
|
+
attr_accessor :backoff # :nodoc:
|
52
|
+
end
|
53
|
+
# Set the default values
|
54
|
+
self.retries = 3
|
55
|
+
self.grpc_codes = [14]
|
56
|
+
self.backoff = ->(retries) { sleep retries.to_i }
|
57
|
+
|
58
|
+
##
|
59
|
+
# @private
|
60
|
+
# Creates a new Backoff object to catch common errors when calling
|
61
|
+
# the Google API and handle the error by retrying the call.
|
62
|
+
#
|
63
|
+
# Google::Cloud::Core::GrpcBackoff.new(options).execute do
|
64
|
+
# datastore.lookup lookup_ref
|
65
|
+
# end
|
66
|
+
def initialize options = {}
|
67
|
+
@retries = (options[:retries] || GrpcBackoff.retries).to_i
|
68
|
+
@grpc_codes = (options[:grpc_codes] || GrpcBackoff.grpc_codes).to_a
|
69
|
+
@backoff = options[:backoff] || GrpcBackoff.backoff
|
70
|
+
end
|
71
|
+
|
72
|
+
# @private
|
73
|
+
def execute
|
74
|
+
current_retries = 0
|
75
|
+
loop do
|
76
|
+
begin
|
77
|
+
return yield
|
78
|
+
rescue GRPC::BadStatus => e
|
79
|
+
raise e unless @grpc_codes.include?(e.code) &&
|
80
|
+
(current_retries < @retries)
|
81
|
+
current_retries += 1
|
82
|
+
@backoff.call current_retries
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Copyright 2016 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
|
+
|
16
|
+
require "google/cloud"
|
17
|
+
require "google/protobuf/struct_pb"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Core
|
22
|
+
##
|
23
|
+
# @private Conversion to/from GRPC objects.
|
24
|
+
module GRPCUtils
|
25
|
+
##
|
26
|
+
# @private Convert a Hash to a Google::Protobuf::Struct.
|
27
|
+
def self.hash_to_struct hash
|
28
|
+
# TODO: ArgumentError if hash is not a Hash
|
29
|
+
Google::Protobuf::Struct.new fields:
|
30
|
+
Hash[hash.map { |k, v| [String(k), object_to_value(v)] }]
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# @private Convert a Google::Protobuf::Struct to a Hash.
|
35
|
+
def self.struct_to_hash struct
|
36
|
+
# TODO: ArgumentError if struct is not a Google::Protobuf::Struct
|
37
|
+
Hash[struct.fields.map { |k, v| [k, value_to_object(v)] }]
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @private Convert a Google::Protobuf::Value to an Object.
|
42
|
+
def self.value_to_object value
|
43
|
+
# TODO: ArgumentError if struct is not a Google::Protobuf::Value
|
44
|
+
if value.null_value
|
45
|
+
nil
|
46
|
+
elsif value.number_value
|
47
|
+
value.number_value
|
48
|
+
elsif value.struct_value
|
49
|
+
struct_to_hash value.struct_value
|
50
|
+
elsif value.list_value
|
51
|
+
value.list_value.values.map { |v| value_to_object(v) }
|
52
|
+
elsif !value.bool_value.nil? # Make sure its a bool, not nil
|
53
|
+
value.bool_value
|
54
|
+
else
|
55
|
+
nil # just in case
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# @private Convert an Object to a Google::Protobuf::Value.
|
61
|
+
def self.object_to_value obj
|
62
|
+
case obj
|
63
|
+
when String then Google::Protobuf::Value.new string_value: obj
|
64
|
+
when Array then Google::Protobuf::ListValue.new(values:
|
65
|
+
obj.map { |o| object_to_value(o) })
|
66
|
+
when Hash then Google::Protobuf::Value.new struct_value:
|
67
|
+
hash_to_struct(obj)
|
68
|
+
when Numeric then Google::Protobuf::Value.new number_value: obj
|
69
|
+
when TrueClass then Google::Protobuf::Value.new bool_value: true
|
70
|
+
when FalseClass then Google::Protobuf::Value.new bool_value: false
|
71
|
+
when NilClass then Google::Protobuf::Value.new null_value: :NULL_VALUE
|
72
|
+
else
|
73
|
+
# We could raise ArgumentError here, or we could convert to a string
|
74
|
+
Google::Protobuf::Value.new string_value: obj.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# @private Convert a Google::Protobuf::Map to a Hash
|
80
|
+
def self.map_to_hash map
|
81
|
+
if map.respond_to? :to_h
|
82
|
+
map.to_h
|
83
|
+
else
|
84
|
+
# Enumerable doesn't have to_h on ruby 2.0...
|
85
|
+
Hash[map.to_a]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright 2016 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
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Core
|
19
|
+
VERSION = "0.20.1"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# Copyright 2014 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
|
+
|
16
|
+
require "json"
|
17
|
+
require "signet/oauth_2/client"
|
18
|
+
require "forwardable"
|
19
|
+
require "googleauth"
|
20
|
+
|
21
|
+
module Google
|
22
|
+
module Cloud
|
23
|
+
##
|
24
|
+
# @private
|
25
|
+
# Represents the OAuth 2.0 signing logic.
|
26
|
+
# This class is intended to be inherited by API-specific classes
|
27
|
+
# which overrides the SCOPE constant.
|
28
|
+
class Credentials
|
29
|
+
TOKEN_CREDENTIAL_URI = "https://accounts.google.com/o/oauth2/token"
|
30
|
+
AUDIENCE = "https://accounts.google.com/o/oauth2/token"
|
31
|
+
SCOPE = []
|
32
|
+
PATH_ENV_VARS = %w(GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
|
33
|
+
JSON_ENV_VARS = %w(GOOGLE_CLOUD_KEYFILE_JSON GCLOUD_KEYFILE_JSON)
|
34
|
+
DEFAULT_PATHS = ["~/.config/gcloud/application_default_credentials.json"]
|
35
|
+
|
36
|
+
attr_accessor :client
|
37
|
+
|
38
|
+
##
|
39
|
+
# Delegate client methods to the client object.
|
40
|
+
extend Forwardable
|
41
|
+
def_delegators :@client,
|
42
|
+
:token_credential_uri, :audience,
|
43
|
+
:scope, :issuer, :signing_key
|
44
|
+
|
45
|
+
def initialize keyfile, scope: nil
|
46
|
+
verify_keyfile_provided! keyfile
|
47
|
+
if keyfile.is_a? Signet::OAuth2::Client
|
48
|
+
@client = keyfile
|
49
|
+
elsif keyfile.is_a? Hash
|
50
|
+
hash = stringify_hash_keys keyfile
|
51
|
+
hash["scope"] ||= scope
|
52
|
+
@client = init_client hash
|
53
|
+
else
|
54
|
+
verify_keyfile_exists! keyfile
|
55
|
+
json = JSON.parse ::File.read(keyfile)
|
56
|
+
json["scope"] ||= scope
|
57
|
+
@client = init_client json
|
58
|
+
end
|
59
|
+
@client.fetch_access_token!
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Returns the default credentials.
|
64
|
+
#
|
65
|
+
def self.default scope: nil
|
66
|
+
env = ->(v) { ENV[v] }
|
67
|
+
json = ->(v) { JSON.parse ENV[v] rescue nil unless ENV[v].nil? }
|
68
|
+
path = ->(p) { ::File.file? p }
|
69
|
+
|
70
|
+
# First try to find keyfile file from environment variables.
|
71
|
+
self::PATH_ENV_VARS.map(&env).reject(&:nil?).select(&path)
|
72
|
+
.each do |file|
|
73
|
+
return new file, scope: scope
|
74
|
+
end
|
75
|
+
# Second try to find keyfile json from environment variables.
|
76
|
+
self::JSON_ENV_VARS.map(&json).reject(&:nil?).each do |hash|
|
77
|
+
return new hash, scope: scope
|
78
|
+
end
|
79
|
+
# Third try to find keyfile file from known file paths.
|
80
|
+
self::DEFAULT_PATHS.select(&path).each do |file|
|
81
|
+
return new file, scope: scope
|
82
|
+
end
|
83
|
+
# Finally get instantiated client from Google::Auth.
|
84
|
+
scope ||= self::SCOPE
|
85
|
+
client = Google::Auth.get_application_default scope
|
86
|
+
new client
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
##
|
92
|
+
# Verify that the keyfile argument is provided.
|
93
|
+
def verify_keyfile_provided! keyfile
|
94
|
+
fail "You must provide a keyfile to connect with." if keyfile.nil?
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Verify that the keyfile argument is a file.
|
99
|
+
def verify_keyfile_exists! keyfile
|
100
|
+
exists = ::File.file? keyfile
|
101
|
+
fail "The keyfile '#{keyfile}' is not a valid file." unless exists
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Initializes the Signet client.
|
106
|
+
def init_client keyfile
|
107
|
+
client_opts = client_options keyfile
|
108
|
+
Signet::OAuth2::Client.new client_opts
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# returns a new Hash with string keys instead of symbol keys.
|
113
|
+
def stringify_hash_keys hash
|
114
|
+
Hash[hash.map { |(k, v)| [k.to_s, v] }]
|
115
|
+
end
|
116
|
+
|
117
|
+
def client_options options
|
118
|
+
# Keyfile options have higher priority over constructor defaults
|
119
|
+
options["token_credential_uri"] ||= self.class::TOKEN_CREDENTIAL_URI
|
120
|
+
options["audience"] ||= self.class::AUDIENCE
|
121
|
+
options["scope"] ||= self.class::SCOPE
|
122
|
+
|
123
|
+
# client options for initializing signet client
|
124
|
+
{ token_credential_uri: options["token_credential_uri"],
|
125
|
+
audience: options["audience"],
|
126
|
+
scope: Array(options["scope"]),
|
127
|
+
issuer: options["client_email"],
|
128
|
+
signing_key: OpenSSL::PKey::RSA.new(options["private_key"]) }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
# Copyright 2015 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
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
##
|
19
|
+
# Base google-cloud exception class.
|
20
|
+
class Error < StandardError
|
21
|
+
# @private Create a new error object from a client error
|
22
|
+
def self.from_error error
|
23
|
+
klass = if error.respond_to? :code
|
24
|
+
grpc_error_class_for error.code
|
25
|
+
elsif error.respond_to? :status_code
|
26
|
+
gapi_error_class_for error.status_code
|
27
|
+
else
|
28
|
+
self
|
29
|
+
end
|
30
|
+
klass.new error.message
|
31
|
+
end
|
32
|
+
|
33
|
+
# @private Identify the subclass for a gRPC error
|
34
|
+
def self.grpc_error_class_for grpc_error_code
|
35
|
+
# The gRPC status code 0 is for a successful response.
|
36
|
+
# So there is no error subclass for a 0 status code, use current class.
|
37
|
+
[self, CanceledError, UnknownError, InvalidArgumentError,
|
38
|
+
DeadlineExceededError, NotFoundError, AlreadyExistsError,
|
39
|
+
PermissionDeniedError, ResourceExhaustedError, FailedPreconditionError,
|
40
|
+
AbortedError, OutOfRangeError, UnimplementedError, InternalError,
|
41
|
+
UnavailableError, DataLossError, UnauthenticatedError
|
42
|
+
][grpc_error_code] || self
|
43
|
+
end
|
44
|
+
|
45
|
+
# @private Identify the subclass for a Google API Client error
|
46
|
+
def self.gapi_error_class_for http_status_code
|
47
|
+
# The http status codes mapped to their error classes.
|
48
|
+
{ 400 => InvalidArgumentError, # FailedPreconditionError/OutOfRangeError
|
49
|
+
401 => UnauthenticatedError,
|
50
|
+
403 => PermissionDeniedError,
|
51
|
+
404 => NotFoundError,
|
52
|
+
409 => AlreadyExistsError, # AbortedError
|
53
|
+
429 => ResourceExhaustedError,
|
54
|
+
499 => CanceledError,
|
55
|
+
500 => InternalError, # UnknownError/DataLossError
|
56
|
+
501 => UnimplementedError,
|
57
|
+
503 => UnavailableError,
|
58
|
+
504 => DeadlineExceededError
|
59
|
+
}[http_status_code] || self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Canceled indicates the operation was cancelled (typically by the caller).
|
65
|
+
class CanceledError < Error
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Unknown error. An example of where this error may be returned is
|
70
|
+
# if a Status value received from another address space belongs to
|
71
|
+
# an error-space that is not known in this address space. Also
|
72
|
+
# errors raised by APIs that do not return enough error information
|
73
|
+
# may be converted to this error.
|
74
|
+
class UnknownError < Error
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# InvalidArgument indicates client specified an invalid argument.
|
79
|
+
# Note that this differs from FailedPrecondition. It indicates arguments
|
80
|
+
# that are problematic regardless of the state of the system
|
81
|
+
# (e.g., a malformed file name).
|
82
|
+
class InvalidArgumentError < Error
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# DeadlineExceeded means operation expired before completion.
|
87
|
+
# For operations that change the state of the system, this error may be
|
88
|
+
# returned even if the operation has completed successfully. For
|
89
|
+
# example, a successful response from a server could have been delayed
|
90
|
+
# long enough for the deadline to expire.
|
91
|
+
class DeadlineExceededError < Error
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# NotFound means some requested entity (e.g., file or directory) was
|
96
|
+
# not found.
|
97
|
+
class NotFoundError < Error
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# AlreadyExists means an attempt to create an entity failed because one
|
102
|
+
# already exists.
|
103
|
+
class AlreadyExistsError < Error
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# PermissionDenied indicates the caller does not have permission to
|
108
|
+
# execute the specified operation. It must not be used for rejections
|
109
|
+
# caused by exhausting some resource (use ResourceExhausted
|
110
|
+
# instead for those errors). It must not be
|
111
|
+
# used if the caller cannot be identified (use Unauthenticated
|
112
|
+
# instead for those errors).
|
113
|
+
class PermissionDeniedError < Error
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Unauthenticated indicates the request does not have valid
|
118
|
+
# authentication credentials for the operation.
|
119
|
+
class UnauthenticatedError < Error
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# ResourceExhausted indicates some resource has been exhausted, perhaps
|
124
|
+
# a per-user quota, or perhaps the entire file system is out of space.
|
125
|
+
class ResourceExhaustedError < Error
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# FailedPrecondition indicates operation was rejected because the
|
130
|
+
# system is not in a state required for the operation's execution.
|
131
|
+
# For example, directory to be deleted may be non-empty, an rmdir
|
132
|
+
# operation is applied to a non-directory, etc.
|
133
|
+
#
|
134
|
+
# A litmus test that may help a service implementor in deciding
|
135
|
+
# between FailedPrecondition, Aborted, and Unavailable:
|
136
|
+
# (a) Use Unavailable if the client can retry just the failing call.
|
137
|
+
# (b) Use Aborted if the client should retry at a higher-level
|
138
|
+
# (e.g., restarting a read-modify-write sequence).
|
139
|
+
# (c) Use FailedPrecondition if the client should not retry until
|
140
|
+
# the system state has been explicitly fixed. E.g., if an "rmdir"
|
141
|
+
# fails because the directory is non-empty, FailedPrecondition
|
142
|
+
# should be returned since the client should not retry unless
|
143
|
+
# they have first fixed up the directory by deleting files from it.
|
144
|
+
# (d) Use FailedPrecondition if the client performs conditional
|
145
|
+
# REST Get/Update/Delete on a resource and the resource on the
|
146
|
+
# server does not match the condition. E.g., conflicting
|
147
|
+
# read-modify-write on the same resource.
|
148
|
+
class FailedPreconditionError < Error
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Aborted indicates the operation was aborted, typically due to a
|
153
|
+
# concurrency issue like sequencer check failures, transaction aborts,
|
154
|
+
# etc.
|
155
|
+
#
|
156
|
+
# See litmus test above for deciding between FailedPrecondition,
|
157
|
+
# Aborted, and Unavailable.
|
158
|
+
class AbortedError < Error
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# OutOfRange means operation was attempted past the valid range.
|
163
|
+
# E.g., seeking or reading past end of file.
|
164
|
+
#
|
165
|
+
# Unlike InvalidArgument, this error indicates a problem that may
|
166
|
+
# be fixed if the system state changes. For example, a 32-bit file
|
167
|
+
# system will generate InvalidArgument if asked to read at an
|
168
|
+
# offset that is not in the range [0,2^32-1], but it will generate
|
169
|
+
# OutOfRange if asked to read from an offset past the current
|
170
|
+
# file size.
|
171
|
+
#
|
172
|
+
# There is a fair bit of overlap between FailedPrecondition and
|
173
|
+
# OutOfRange. We recommend using OutOfRange (the more specific
|
174
|
+
# error) when it applies so that callers who are iterating through
|
175
|
+
# a space can easily look for an OutOfRange error to detect when
|
176
|
+
# they are done.
|
177
|
+
class OutOfRangeError < Error
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Unimplemented indicates operation is not implemented or not
|
182
|
+
# supported/enabled in this service.
|
183
|
+
class UnimplementedError < Error
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Internal errors. Means some invariants expected by underlying
|
188
|
+
# system has been broken. If you see one of these errors,
|
189
|
+
# something is very broken.
|
190
|
+
class InternalError < Error
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Unavailable indicates the service is currently unavailable.
|
195
|
+
# This is a most likely a transient condition and may be corrected
|
196
|
+
# by retrying with a backoff.
|
197
|
+
#
|
198
|
+
# See litmus test above for deciding between FailedPrecondition,
|
199
|
+
# Aborted, and Unavailable.
|
200
|
+
class UnavailableError < Error
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# DataLoss indicates unrecoverable data loss or corruption.
|
205
|
+
class DataLossError < Error
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google-cloud-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.20.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Moore
|
8
|
+
- Chris Smith
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-08-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '5.9'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '5.9'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest-autotest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: minitest-focus
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.1'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.1'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: minitest-rg
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '5.2'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '5.2'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: autotest-suffix
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.1'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.1'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rubocop
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "<="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 0.35.1
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "<="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 0.35.1
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: simplecov
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0.9'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0.9'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: yard
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0.9'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.9'
|
126
|
+
description: google-cloud-core is the internal shared library for google-cloud-ruby.
|
127
|
+
email:
|
128
|
+
- mike@blowmage.com
|
129
|
+
- quartzmo@gmail.com
|
130
|
+
executables: []
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- lib/google/cloud.rb
|
135
|
+
- lib/google/cloud/core/backoff.rb
|
136
|
+
- lib/google/cloud/core/gce.rb
|
137
|
+
- lib/google/cloud/core/grpc_backoff.rb
|
138
|
+
- lib/google/cloud/core/grpc_utils.rb
|
139
|
+
- lib/google/cloud/core/version.rb
|
140
|
+
- lib/google/cloud/credentials.rb
|
141
|
+
- lib/google/cloud/errors.rb
|
142
|
+
homepage: http://googlecloudplatform.github.io/google-cloud-ruby/
|
143
|
+
licenses:
|
144
|
+
- Apache-2.0
|
145
|
+
metadata: {}
|
146
|
+
post_install_message:
|
147
|
+
rdoc_options: []
|
148
|
+
require_paths:
|
149
|
+
- lib
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: 2.0.0
|
155
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirements: []
|
161
|
+
rubyforge_project:
|
162
|
+
rubygems_version: 2.6.4
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: Internal shared library for google-cloud-ruby
|
166
|
+
test_files: []
|