fog-google 0.2.0 → 0.3.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 +4 -4
- data/.gitignore +1 -0
- data/README.md +7 -3
- data/examples/pubsub/subscriptions.rb +54 -0
- data/examples/pubsub/topics.rb +33 -0
- data/fog-google.gemspec +2 -2
- data/lib/fog/compute/google.rb +4 -884
- data/lib/fog/compute/google/mock.rb +871 -0
- data/lib/fog/compute/google/real.rb +22 -0
- data/lib/fog/dns/google.rb +3 -42
- data/lib/fog/dns/google/mock.rb +33 -0
- data/lib/fog/dns/google/real.rb +19 -0
- data/lib/fog/google.rb +14 -208
- data/lib/fog/google/mock.rb +14 -0
- data/lib/fog/google/models/pubsub/received_message.rb +40 -0
- data/lib/fog/google/models/pubsub/subscription.rb +86 -0
- data/lib/fog/google/models/pubsub/subscriptions.rb +32 -0
- data/lib/fog/google/models/pubsub/topic.rb +72 -0
- data/lib/fog/google/models/pubsub/topics.rb +31 -0
- data/lib/fog/google/monitoring.rb +3 -45
- data/lib/fog/google/monitoring/mock.rb +35 -0
- data/lib/fog/google/monitoring/real.rb +20 -0
- data/lib/fog/google/pubsub.rb +59 -0
- data/lib/fog/google/pubsub/mock.rb +34 -0
- data/lib/fog/google/pubsub/real.rb +20 -0
- data/lib/fog/google/requests/pubsub/acknowledge_subscription.rb +46 -0
- data/lib/fog/google/requests/pubsub/create_subscription.rb +57 -0
- data/lib/fog/google/requests/pubsub/create_topic.rb +36 -0
- data/lib/fog/google/requests/pubsub/delete_subscription.rb +28 -0
- data/lib/fog/google/requests/pubsub/delete_topic.rb +29 -0
- data/lib/fog/google/requests/pubsub/get_subscription.rb +44 -0
- data/lib/fog/google/requests/pubsub/get_topic.rb +41 -0
- data/lib/fog/google/requests/pubsub/list_subscriptions.rb +39 -0
- data/lib/fog/google/requests/pubsub/list_topics.rb +33 -0
- data/lib/fog/google/requests/pubsub/publish_topic.rb +61 -0
- data/lib/fog/google/requests/pubsub/pull_subscription.rb +77 -0
- data/lib/fog/google/shared.rb +191 -0
- data/lib/fog/google/sql.rb +3 -50
- data/lib/fog/google/sql/mock.rb +40 -0
- data/lib/fog/google/sql/real.rb +20 -0
- data/lib/fog/google/version.rb +1 -1
- data/lib/fog/storage/google_json.rb +4 -99
- data/lib/fog/storage/google_json/mock.rb +18 -0
- data/lib/fog/storage/google_json/real.rb +64 -0
- data/lib/fog/storage/google_json/utils.rb +32 -0
- data/lib/fog/storage/google_xml.rb +4 -260
- data/lib/fog/storage/google_xml/mock.rb +102 -0
- data/lib/fog/storage/google_xml/models/file.rb +14 -4
- data/lib/fog/storage/google_xml/real.rb +106 -0
- data/lib/fog/storage/google_xml/utils.rb +66 -0
- data/tests/models/pubsub/received_message_tests.rb +18 -0
- data/tests/models/pubsub/subscription_tests.rb +26 -0
- data/tests/models/pubsub/subscriptions_tests.rb +33 -0
- data/tests/models/pubsub/topic_tests.rb +18 -0
- data/tests/models/pubsub/topics_tests.rb +27 -0
- metadata +50 -14
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Create a topic on the remote service.
|
6
|
+
#
|
7
|
+
# @param topic_name [#to_s] name of topic to create; note that it must
|
8
|
+
# obey the naming rules for a topic (e.g.
|
9
|
+
# 'projects/myProject/topics/my_topic')
|
10
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/create
|
11
|
+
def create_topic(topic_name)
|
12
|
+
api_method = @pubsub.projects.topics.create
|
13
|
+
parameters = {
|
14
|
+
"name" => topic_name.to_s
|
15
|
+
}
|
16
|
+
|
17
|
+
request(api_method, parameters)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Mock
|
22
|
+
def create_topic(topic_name)
|
23
|
+
data = {
|
24
|
+
"name" => topic_name
|
25
|
+
}
|
26
|
+
self.data[:topics][topic_name] = data
|
27
|
+
|
28
|
+
body = data.clone
|
29
|
+
status = 200
|
30
|
+
|
31
|
+
build_excon_response(body, status)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Delete a subscription on the remote service.
|
6
|
+
#
|
7
|
+
# @param subscription_name [#to_s] name of subscription to delete
|
8
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions/delete
|
9
|
+
def delete_subscription(subscription_name)
|
10
|
+
api_method = @pubsub.projects.subscriptions.delete
|
11
|
+
parameters = {
|
12
|
+
"subscription" => subscription_name.to_s
|
13
|
+
}
|
14
|
+
|
15
|
+
request(api_method, parameters)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Mock
|
20
|
+
def delete_subscription(subscription_name)
|
21
|
+
data[:subscriptions].delete(subscription_name)
|
22
|
+
|
23
|
+
build_excon_response(nil, 200)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Delete a topic on the remote service.
|
6
|
+
#
|
7
|
+
# @param topic_name [#to_s] name of topic to delete
|
8
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/delete
|
9
|
+
def delete_topic(topic_name)
|
10
|
+
api_method = @pubsub.projects.topics.delete
|
11
|
+
parameters = {
|
12
|
+
"topic" => topic_name.to_s
|
13
|
+
}
|
14
|
+
|
15
|
+
request(api_method, parameters)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Mock
|
20
|
+
def delete_topic(topic_name)
|
21
|
+
data[:topics].delete(topic_name)
|
22
|
+
|
23
|
+
status = 200
|
24
|
+
build_excon_response(nil, status)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Retrieves a subscription by name from the remote service.
|
6
|
+
#
|
7
|
+
# @param subscription_name [#to_s] name of subscription to retrieve
|
8
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/get
|
9
|
+
def get_subscription(subscription_name)
|
10
|
+
api_method = @pubsub.projects.subscriptions.get
|
11
|
+
parameters = {
|
12
|
+
"subscription" => subscription_name.to_s
|
13
|
+
}
|
14
|
+
|
15
|
+
request(api_method, parameters)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Mock
|
20
|
+
def get_subscription(subscription_name)
|
21
|
+
sub = data[:subscriptions][subscription_name]
|
22
|
+
if sub.nil?
|
23
|
+
subscription_resource = subscription_name.split("/")[-1]
|
24
|
+
body = {
|
25
|
+
"error" => {
|
26
|
+
"code" => 404,
|
27
|
+
"message" => "Resource not found (resource=#{subscription_resource}).",
|
28
|
+
"status" => "NOT_FOUND"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
return build_excon_response(body, 404)
|
32
|
+
end
|
33
|
+
|
34
|
+
body = sub.select do |k, _|
|
35
|
+
%w(name topic pushConfig ackDeadlineSeconds).include?(k)
|
36
|
+
end
|
37
|
+
status = 200
|
38
|
+
|
39
|
+
build_excon_response(body, status)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Retrieves a resource describing a topic.
|
6
|
+
#
|
7
|
+
# @param topic_name [#to_s] name of topic to retrieve
|
8
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/get
|
9
|
+
def get_topic(topic_name)
|
10
|
+
api_method = @pubsub.projects.topics.get
|
11
|
+
parameters = {
|
12
|
+
"topic" => topic_name.to_s
|
13
|
+
}
|
14
|
+
|
15
|
+
request(api_method, parameters)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Mock
|
20
|
+
def get_topic(topic_name)
|
21
|
+
if !data[:topics].key?(topic_name)
|
22
|
+
topic_resource = topic_name.split("/")[-1]
|
23
|
+
body = {
|
24
|
+
"error" => {
|
25
|
+
"code" => 404,
|
26
|
+
"message" => "Resource not found (resource=#{topic_resource}).",
|
27
|
+
"status" => "NOT_FOUND"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
status = 404
|
31
|
+
else
|
32
|
+
body = data[:topics][topic_name].clone
|
33
|
+
status = 200
|
34
|
+
end
|
35
|
+
|
36
|
+
build_excon_response(body, status)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Gets a list of all subscriptions for a given project.
|
6
|
+
#
|
7
|
+
# @param_name project [#to_s] Project path to list subscriptions under;
|
8
|
+
# must be a project url prefix (e.g. 'projects/my-project'). If nil,
|
9
|
+
# the project configured on the client is used.
|
10
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/list
|
11
|
+
def list_subscriptions(project = nil)
|
12
|
+
api_method = @pubsub.projects.subscriptions.list
|
13
|
+
parameters = {
|
14
|
+
"project" => (project.nil? ? "projects/#{@project}" : project.to_s)
|
15
|
+
}
|
16
|
+
|
17
|
+
request(api_method, parameters)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Mock
|
22
|
+
def list_subscriptions(_project = nil)
|
23
|
+
subs = data[:subscriptions].values.map do |sub|
|
24
|
+
# Filter out any keys that aren't part of the response object
|
25
|
+
sub.select do |k, _|
|
26
|
+
%w(name topic pushConfig ackDeadlineSeconds).include?(k)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
body = {
|
31
|
+
"subscriptions" => subs
|
32
|
+
}
|
33
|
+
status = 200
|
34
|
+
build_excon_response(body, status)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Gets a list of all topics for a given project.
|
6
|
+
#
|
7
|
+
# @param_name project [#to_s] Project path to list topics under; must
|
8
|
+
# be a project url prefix (e.g. 'projects/my-project'). If nil, the
|
9
|
+
# project configured on the client is used.
|
10
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/list
|
11
|
+
def list_topics(project = nil)
|
12
|
+
api_method = @pubsub.projects.topics.list
|
13
|
+
parameters = {
|
14
|
+
"project" => (project.nil? ? "projects/#{@project}" : project.to_s)
|
15
|
+
}
|
16
|
+
|
17
|
+
request(api_method, parameters)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Mock
|
22
|
+
def list_topics(_project = nil)
|
23
|
+
body = {
|
24
|
+
"topics" => data[:topics].values
|
25
|
+
}
|
26
|
+
status = 200
|
27
|
+
|
28
|
+
build_excon_response(body, status)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Publish a list of messages to a topic.
|
6
|
+
#
|
7
|
+
# @param messages [Array<Hash>] List of messages to be published to a
|
8
|
+
# topic; each hash should have a value defined for 'data' or for
|
9
|
+
# 'attributes' (or both). Note that the value associated with 'data'
|
10
|
+
# must be base64 encoded.
|
11
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/publish
|
12
|
+
def publish_topic(topic, messages)
|
13
|
+
api_method = @pubsub.projects.topics.publish
|
14
|
+
|
15
|
+
parameters = {
|
16
|
+
"topic" => topic
|
17
|
+
}
|
18
|
+
|
19
|
+
body = {
|
20
|
+
"messages" => messages
|
21
|
+
}
|
22
|
+
|
23
|
+
request(api_method, parameters, body)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Mock
|
28
|
+
def publish_topic(topic, messages)
|
29
|
+
if data[:topics].key?(topic)
|
30
|
+
published_messages = messages.map do |msg|
|
31
|
+
msg.merge("messageId" => Fog::Mock.random_letters(16), "publishTime" => Time.now.iso8601)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Gather the subscriptions and publish
|
35
|
+
data[:subscriptions].values.each do |sub|
|
36
|
+
next unless sub["topic"] == topic
|
37
|
+
sub[:messages] += published_messages
|
38
|
+
end
|
39
|
+
|
40
|
+
body = {
|
41
|
+
"messageIds" => published_messages.map { |msg| msg["messageId"] }
|
42
|
+
}
|
43
|
+
status = 200
|
44
|
+
else
|
45
|
+
topic_resource = topic_name.split("/")[-1]
|
46
|
+
body = {
|
47
|
+
"error" => {
|
48
|
+
"code" => 404,
|
49
|
+
"message" => "Resource not found (resource=#{topic_resource}).",
|
50
|
+
"status" => "NOT_FOUND"
|
51
|
+
}
|
52
|
+
}
|
53
|
+
status = 404
|
54
|
+
end
|
55
|
+
|
56
|
+
build_excon_response(body, status)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
class Pubsub
|
4
|
+
class Real
|
5
|
+
# Pulls from a subscription. If option 'return_immediately' is
|
6
|
+
# false, then this method blocks until one or more messages is
|
7
|
+
# available or the remote server closes the connection.
|
8
|
+
#
|
9
|
+
# @param subscription [Subscription, #to_s] subscription instance or
|
10
|
+
# name of subscription to pull from
|
11
|
+
# @param options [Hash] options to modify the pull request
|
12
|
+
# @option options [Boolean] :return_immediately if true, method returns
|
13
|
+
# after API call; otherwise the connection is held open until
|
14
|
+
# messages are available or the remote server closes the connection
|
15
|
+
# (defaults to true)
|
16
|
+
# @option options [Number] :max_messages maximum number of messages to
|
17
|
+
# retrieve (defaults to 10)
|
18
|
+
# @see https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions/pull
|
19
|
+
def pull_subscription(subscription, options = { :return_immediately => true, :max_messages => 10 })
|
20
|
+
api_method = @pubsub.projects.subscriptions.pull
|
21
|
+
|
22
|
+
parameters = {
|
23
|
+
"subscription" => Fog::Google::Pubsub.subscription_name(subscription)
|
24
|
+
}
|
25
|
+
|
26
|
+
body = {
|
27
|
+
"returnImmediately" => options[:return_immediately],
|
28
|
+
"maxMessages" => options[:max_messages]
|
29
|
+
}
|
30
|
+
|
31
|
+
request(api_method, parameters, body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Mock
|
36
|
+
def pull_subscription(subscription, options = { :return_immediately => true, :max_messages => 10 })
|
37
|
+
# We're going to ignore return_immediately; feel free to add support
|
38
|
+
# if you need it for testing
|
39
|
+
subscription_name = Fog::Google::Pubsub.subscription_name(subscription)
|
40
|
+
sub = data[:subscriptions][subscription_name]
|
41
|
+
|
42
|
+
if sub.nil?
|
43
|
+
subscription_resource = subscription_name.split("/")[-1]
|
44
|
+
body = {
|
45
|
+
"error" => {
|
46
|
+
"code" => 404,
|
47
|
+
"message" => "Resource not found (resource=#{subscription_resource}).",
|
48
|
+
"status" => "NOT_FOUND"
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return build_excon_response(body, 404)
|
52
|
+
end
|
53
|
+
|
54
|
+
# This implementation is a bit weak; instead of "hiding" messages for
|
55
|
+
# some period of time after they are pulled, instead we always return
|
56
|
+
# them until acknowledged. This might cause issues with clients that
|
57
|
+
# refuse to acknowledge.
|
58
|
+
#
|
59
|
+
# Also, note that here we use the message id as the ack id - again,
|
60
|
+
# this might cause problems with some strange-behaving clients.
|
61
|
+
msgs = sub[:messages].take(options[:max_messages]).map do |msg|
|
62
|
+
{
|
63
|
+
"ackId" => msg["messageId"],
|
64
|
+
"message" => msg
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
body = {
|
69
|
+
"receivedMessages" => msgs
|
70
|
+
}
|
71
|
+
status = 200
|
72
|
+
build_excon_response(body, status)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
module Fog
|
2
|
+
module Google
|
3
|
+
module Shared
|
4
|
+
attr_reader :project, :api_version, :api_url
|
5
|
+
|
6
|
+
##
|
7
|
+
# Initializes shared attributes
|
8
|
+
#
|
9
|
+
# @param [String] project Google Cloud Project
|
10
|
+
# @param [String] api_version Google API version
|
11
|
+
# @param [String] base_url Google API base url
|
12
|
+
# @return [void]
|
13
|
+
def shared_initialize(project, api_version, base_url)
|
14
|
+
@project = project
|
15
|
+
@api_version = api_version
|
16
|
+
@api_url = base_url + api_version + "/projects/"
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Initializes the Google API Client
|
21
|
+
#
|
22
|
+
# @param [Hash] options Google API options
|
23
|
+
# @option options [String] :google_client_email A @developer.gserviceaccount.com email address to use
|
24
|
+
# @option options [String] :google_key_location The location of a pkcs12 key file
|
25
|
+
# @option options [String] :google_key_string The content of the pkcs12 key file
|
26
|
+
# @option options [String] :google_json_key_location The location of a JSON key file
|
27
|
+
# @option options [String] :google_json_key_string The content of the JSON key file
|
28
|
+
# @option options [String] :google_api_scope_url The access scope URLs
|
29
|
+
# @option options [String] :app_name The app name to set in the user agent
|
30
|
+
# @option options [String] :app_version The app version to set in the user agent
|
31
|
+
# @option options [Google::APIClient] :google_client Existing Google API Client
|
32
|
+
# @return [Google::APIClient] Google API Client
|
33
|
+
# @raises [ArgumentError] If there is any missing argument
|
34
|
+
def initialize_google_client(options)
|
35
|
+
# NOTE: loaded here to avoid requiring this as a core Fog dependency
|
36
|
+
begin
|
37
|
+
require "google/api_client"
|
38
|
+
rescue LoadError => error
|
39
|
+
Fog::Logger.warning("Please install the google-api-client gem before using this provider")
|
40
|
+
raise error
|
41
|
+
end
|
42
|
+
|
43
|
+
# User can provide an existing Google API Client
|
44
|
+
client = options[:google_client]
|
45
|
+
return client unless client.nil?
|
46
|
+
|
47
|
+
# Create a signing key
|
48
|
+
signing_key = create_signing_key(options)
|
49
|
+
|
50
|
+
# Validate required arguments
|
51
|
+
unless options[:google_client_email]
|
52
|
+
raise ArgumentError.new("Missing required arguments: google_client_email")
|
53
|
+
end
|
54
|
+
|
55
|
+
unless options[:google_api_scope_url]
|
56
|
+
raise ArgumentError.new("Missing required arguments: google_api_scope_url")
|
57
|
+
end
|
58
|
+
|
59
|
+
# Create a new Google API Client
|
60
|
+
new_pk12_google_client(
|
61
|
+
options[:google_client_email],
|
62
|
+
signing_key,
|
63
|
+
options[:google_api_scope_url],
|
64
|
+
options[:app_name],
|
65
|
+
options[:app_version]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Creates a Google signing key
|
71
|
+
#
|
72
|
+
def create_signing_key(options)
|
73
|
+
if options[:google_json_key_location] || options[:google_json_key_string]
|
74
|
+
if options[:google_json_key_location]
|
75
|
+
json_key_location = File.expand_path(options[:google_json_key_location])
|
76
|
+
json_key = File.open(json_key_location, "r", &:read)
|
77
|
+
else
|
78
|
+
json_key = options[:google_json_key_string]
|
79
|
+
end
|
80
|
+
|
81
|
+
json_key_hash = Fog::JSON.decode(json_key)
|
82
|
+
unless json_key_hash.key?("client_email") || json_key_hash.key?("private_key")
|
83
|
+
raise ArgumentError.new("Invalid Google JSON key")
|
84
|
+
end
|
85
|
+
|
86
|
+
options[:google_client_email] = json_key_hash["client_email"]
|
87
|
+
::Google::APIClient::KeyUtils.load_from_pem(json_key_hash["private_key"], "notasecret")
|
88
|
+
elsif options[:google_key_location] || options[:google_key_string]
|
89
|
+
google_key =
|
90
|
+
if options[:google_key_location]
|
91
|
+
File.expand_path(options[:google_key_location])
|
92
|
+
else
|
93
|
+
options[:google_key_string]
|
94
|
+
end
|
95
|
+
|
96
|
+
::Google::APIClient::KeyUtils.load_from_pkcs12(google_key, "notasecret")
|
97
|
+
else
|
98
|
+
raise ArgumentError.new("Missing required arguments: google_key_location, google_key_string, " \
|
99
|
+
"google_json_key_location or google_json_key_string")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Create a Google API Client with a user email and a pkcs12 key
|
105
|
+
#
|
106
|
+
# @param [String] google_client_email A @developer.gserviceaccount.com email address to use
|
107
|
+
# @param [OpenSSL::PKey] signing_key The private key for signing
|
108
|
+
# @param [String] google_api_scope_url Access scope URLs
|
109
|
+
# @param [String] app_name The app name to set in the user agent
|
110
|
+
# @param [String] app_version The app version to set in the user agent
|
111
|
+
# @return [Google::APIClient] Google API Client
|
112
|
+
def new_pk12_google_client(google_client_email, signing_key, google_api_scope_url, app_name = nil, app_version = nil)
|
113
|
+
application_name = app_name.nil? ? "fog" : "#{app_name}/#{app_version || '0.0.0'} fog"
|
114
|
+
api_client_options = {
|
115
|
+
:application_name => application_name,
|
116
|
+
:application_version => Fog::Google::VERSION
|
117
|
+
}
|
118
|
+
client = ::Google::APIClient.new(api_client_options)
|
119
|
+
|
120
|
+
client.authorization = Signet::OAuth2::Client.new(
|
121
|
+
:audience => "https://accounts.google.com/o/oauth2/token",
|
122
|
+
:auth_provider_x509_cert_url => "https://www.googleapis.com/oauth2/v1/certs",
|
123
|
+
:client_x509_cert_url => "https://www.googleapis.com/robot/v1/metadata/x509/#{google_client_email}",
|
124
|
+
:issuer => google_client_email,
|
125
|
+
:scope => google_api_scope_url,
|
126
|
+
:signing_key => signing_key,
|
127
|
+
:token_credential_uri => "https://accounts.google.com/o/oauth2/token"
|
128
|
+
)
|
129
|
+
client.authorization.fetch_access_token!
|
130
|
+
|
131
|
+
client
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Executes a request and wraps it in a result object
|
136
|
+
#
|
137
|
+
# @param [Google::APIClient::Method] api_method The method object or the RPC name of the method being executed
|
138
|
+
# @param [Hash] parameters The parameters to send to the method
|
139
|
+
# @param [Hash] body_object The body object of the request
|
140
|
+
# @return [Excon::Response] The result from the API
|
141
|
+
def request(api_method, parameters, body_object = nil, media = nil)
|
142
|
+
client_parms = {
|
143
|
+
:api_method => api_method,
|
144
|
+
:parameters => parameters
|
145
|
+
}
|
146
|
+
# The Google API complains when given null values for enums, so just don't pass it any null fields
|
147
|
+
# XXX It may still balk if we have a nested object, e.g.:
|
148
|
+
# {:a_field => "string", :a_nested_field => { :an_empty_nested_field => nil } }
|
149
|
+
client_parms[:body_object] = body_object.reject { |_k, v| v.nil? } if body_object
|
150
|
+
client_parms[:media] = media if media
|
151
|
+
|
152
|
+
result = @client.execute(client_parms)
|
153
|
+
|
154
|
+
build_excon_response(result.body.nil? || result.body.empty? ? nil : Fog::JSON.decode(result.body), result.status)
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Builds an Excon response
|
159
|
+
#
|
160
|
+
# @param [Hash] Response body
|
161
|
+
# @param [Integer] Response status
|
162
|
+
# @return [Excon::Response] Excon response
|
163
|
+
def build_excon_response(body, status = 200)
|
164
|
+
response = Excon::Response.new(:body => body, :status => status)
|
165
|
+
if body && body.key?("error")
|
166
|
+
msg = "Google Cloud did not return an error message"
|
167
|
+
|
168
|
+
if body["error"].is_a?(Hash)
|
169
|
+
response.status = body["error"]["code"]
|
170
|
+
if body["error"].key?("errors")
|
171
|
+
msg = body["error"]["errors"].map { |error| error["message"] }.join(", ")
|
172
|
+
elsif body["error"].key?("message")
|
173
|
+
msg = body["error"]["message"]
|
174
|
+
end
|
175
|
+
elsif body["error"].is_a?(Array)
|
176
|
+
msg = body["error"].map { |error| error["code"] }.join(", ")
|
177
|
+
end
|
178
|
+
|
179
|
+
case response.status
|
180
|
+
when 404
|
181
|
+
raise Fog::Errors::NotFound.new(msg)
|
182
|
+
else
|
183
|
+
raise Fog::Errors::Error.new(msg)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
response
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|