fog-google 1.10.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/ruby.yml +34 -0
- data/.github/workflows/stale.yml +23 -0
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +100 -1
- data/README.md +56 -10
- data/ci/docker-image/Dockerfile +3 -3
- data/fog-google.gemspec +4 -4
- data/lib/fog/compute/google.rb +0 -4
- data/lib/fog/compute/google/models/address.rb +1 -1
- data/lib/fog/compute/google/models/addresses.rb +6 -6
- data/lib/fog/compute/google/models/backend_service.rb +1 -1
- data/lib/fog/compute/google/models/disk.rb +3 -3
- data/lib/fog/compute/google/models/disk_types.rb +2 -2
- data/lib/fog/compute/google/models/disks.rb +2 -2
- data/lib/fog/compute/google/models/firewall.rb +2 -2
- data/lib/fog/compute/google/models/firewalls.rb +1 -1
- data/lib/fog/compute/google/models/forwarding_rules.rb +2 -2
- data/lib/fog/compute/google/models/global_addresses.rb +1 -1
- data/lib/fog/compute/google/models/global_forwarding_rules.rb +1 -1
- data/lib/fog/compute/google/models/http_health_check.rb +2 -2
- data/lib/fog/compute/google/models/instance_group_managers.rb +2 -2
- data/lib/fog/compute/google/models/machine_types.rb +2 -2
- data/lib/fog/compute/google/models/operations.rb +3 -3
- data/lib/fog/compute/google/models/server.rb +3 -3
- data/lib/fog/compute/google/models/servers.rb +3 -3
- data/lib/fog/compute/google/models/subnetworks.rb +2 -2
- data/lib/fog/compute/google/models/target_instances.rb +2 -2
- data/lib/fog/compute/google/models/target_pools.rb +2 -2
- data/lib/fog/compute/google/models/url_maps.rb +1 -1
- data/lib/fog/compute/google/requests/abandon_instances.rb +1 -1
- data/lib/fog/compute/google/requests/add_instance_group_instances.rb +3 -3
- data/lib/fog/compute/google/requests/add_server_access_config.rb +3 -3
- data/lib/fog/compute/google/requests/add_target_pool_health_checks.rb +2 -2
- data/lib/fog/compute/google/requests/add_target_pool_instances.rb +2 -2
- data/lib/fog/compute/google/requests/attach_disk.rb +1 -1
- data/lib/fog/compute/google/requests/create_disk_snapshot.rb +1 -1
- data/lib/fog/compute/google/requests/expand_subnetwork_ip_cidr_range.rb +1 -1
- data/lib/fog/compute/google/requests/get_backend_service_health.rb +1 -1
- data/lib/fog/compute/google/requests/get_server_serial_port_output.rb +2 -2
- data/lib/fog/compute/google/requests/get_target_pool_health.rb +1 -1
- data/lib/fog/compute/google/requests/insert_address.rb +2 -2
- data/lib/fog/compute/google/requests/insert_backend_service.rb +1 -1
- data/lib/fog/compute/google/requests/insert_disk.rb +1 -1
- data/lib/fog/compute/google/requests/insert_firewall.rb +1 -1
- data/lib/fog/compute/google/requests/insert_forwarding_rule.rb +1 -1
- data/lib/fog/compute/google/requests/insert_global_address.rb +1 -1
- data/lib/fog/compute/google/requests/insert_global_forwarding_rule.rb +1 -1
- data/lib/fog/compute/google/requests/insert_http_health_check.rb +1 -1
- data/lib/fog/compute/google/requests/insert_image.rb +1 -1
- data/lib/fog/compute/google/requests/insert_instance_group.rb +3 -3
- data/lib/fog/compute/google/requests/insert_instance_group_manager.rb +7 -7
- data/lib/fog/compute/google/requests/insert_instance_template.rb +3 -3
- data/lib/fog/compute/google/requests/insert_network.rb +1 -1
- data/lib/fog/compute/google/requests/insert_route.rb +10 -10
- data/lib/fog/compute/google/requests/insert_server.rb +12 -8
- data/lib/fog/compute/google/requests/insert_ssl_certificate.rb +4 -4
- data/lib/fog/compute/google/requests/insert_subnetwork.rb +1 -1
- data/lib/fog/compute/google/requests/insert_target_http_proxy.rb +3 -3
- data/lib/fog/compute/google/requests/insert_target_https_proxy.rb +4 -4
- data/lib/fog/compute/google/requests/insert_target_instance.rb +1 -1
- data/lib/fog/compute/google/requests/insert_target_pool.rb +1 -1
- data/lib/fog/compute/google/requests/insert_url_map.rb +1 -1
- data/lib/fog/compute/google/requests/invalidate_url_map_cache.rb +1 -1
- data/lib/fog/compute/google/requests/list_addresses.rb +4 -4
- data/lib/fog/compute/google/requests/list_aggregated_addresses.rb +1 -1
- data/lib/fog/compute/google/requests/list_aggregated_disk_types.rb +2 -2
- data/lib/fog/compute/google/requests/list_aggregated_disks.rb +2 -2
- data/lib/fog/compute/google/requests/list_aggregated_forwarding_rules.rb +2 -2
- data/lib/fog/compute/google/requests/list_aggregated_instance_group_managers.rb +4 -4
- data/lib/fog/compute/google/requests/list_aggregated_instance_groups.rb +1 -1
- data/lib/fog/compute/google/requests/list_aggregated_machine_types.rb +2 -2
- data/lib/fog/compute/google/requests/list_aggregated_servers.rb +2 -2
- data/lib/fog/compute/google/requests/list_aggregated_subnetworks.rb +4 -4
- data/lib/fog/compute/google/requests/list_aggregated_target_instances.rb +4 -4
- data/lib/fog/compute/google/requests/list_aggregated_target_pools.rb +4 -4
- data/lib/fog/compute/google/requests/list_disk_types.rb +2 -2
- data/lib/fog/compute/google/requests/list_disks.rb +2 -2
- data/lib/fog/compute/google/requests/list_firewalls.rb +4 -4
- data/lib/fog/compute/google/requests/list_forwarding_rules.rb +2 -2
- data/lib/fog/compute/google/requests/list_global_addresses.rb +5 -5
- data/lib/fog/compute/google/requests/list_global_forwarding_rules.rb +2 -2
- data/lib/fog/compute/google/requests/list_global_operations.rb +4 -4
- data/lib/fog/compute/google/requests/list_http_health_checks.rb +2 -2
- data/lib/fog/compute/google/requests/list_images.rb +2 -2
- data/lib/fog/compute/google/requests/list_instance_group_managers.rb +2 -2
- data/lib/fog/compute/google/requests/list_instance_templates.rb +4 -4
- data/lib/fog/compute/google/requests/list_machine_types.rb +4 -4
- data/lib/fog/compute/google/requests/list_networks.rb +4 -4
- data/lib/fog/compute/google/requests/list_subnetworks.rb +4 -4
- data/lib/fog/compute/google/requests/list_target_pools.rb +4 -4
- data/lib/fog/compute/google/requests/list_url_maps.rb +2 -2
- data/lib/fog/compute/google/requests/patch_firewall.rb +1 -1
- data/lib/fog/compute/google/requests/remove_instance_group_instances.rb +3 -3
- data/lib/fog/compute/google/requests/remove_target_pool_health_checks.rb +2 -2
- data/lib/fog/compute/google/requests/remove_target_pool_instance.rb +2 -2
- data/lib/fog/compute/google/requests/remove_target_pool_instances.rb +2 -2
- data/lib/fog/compute/google/requests/set_common_instance_metadata.rb +2 -2
- data/lib/fog/compute/google/requests/set_forwarding_rule_target.rb +1 -1
- data/lib/fog/compute/google/requests/set_global_forwarding_rule_target.rb +1 -1
- data/lib/fog/compute/google/requests/set_server_metadata.rb +3 -3
- data/lib/fog/compute/google/requests/set_server_tags.rb +2 -2
- data/lib/fog/compute/google/requests/set_snapshot_labels.rb +2 -2
- data/lib/fog/compute/google/requests/set_subnetwork_private_ip_google_access.rb +1 -1
- data/lib/fog/compute/google/requests/set_target_http_proxy_url_map.rb +1 -1
- data/lib/fog/compute/google/requests/set_target_https_proxy_ssl_certificates.rb +1 -1
- data/lib/fog/compute/google/requests/set_target_https_proxy_url_map.rb +1 -1
- data/lib/fog/compute/google/requests/set_target_pool_backup.rb +2 -2
- data/lib/fog/compute/google/requests/update_firewall.rb +1 -1
- data/lib/fog/compute/google/requests/update_http_health_check.rb +1 -1
- data/lib/fog/compute/google/requests/update_url_map.rb +1 -1
- data/lib/fog/compute/google/requests/validate_url_map.rb +1 -1
- data/lib/fog/dns/google/requests/create_change.rb +2 -2
- data/lib/fog/google/models/sql/instance.rb +2 -2
- data/lib/fog/google/requests/monitoring/create_metric_descriptor.rb +8 -8
- data/lib/fog/google/requests/monitoring/create_timeseries.rb +1 -1
- data/lib/fog/google/requests/monitoring/list_timeseries.rb +1 -1
- data/lib/fog/google/requests/pubsub/acknowledge_subscription.rb +1 -1
- data/lib/fog/google/requests/pubsub/create_subscription.rb +3 -3
- data/lib/fog/google/requests/pubsub/pull_subscription.rb +5 -1
- data/lib/fog/google/requests/sql/clone_instance.rb +4 -4
- data/lib/fog/google/requests/sql/delete_user.rb +1 -1
- data/lib/fog/google/requests/sql/export_instance.rb +3 -3
- data/lib/fog/google/requests/sql/import_instance.rb +2 -2
- data/lib/fog/google/requests/sql/insert_backup_run.rb +1 -1
- data/lib/fog/google/requests/sql/insert_instance.rb +2 -2
- data/lib/fog/google/requests/sql/insert_ssl_cert.rb +1 -1
- data/lib/fog/google/requests/sql/insert_user.rb +1 -1
- data/lib/fog/google/requests/sql/restore_instance_backup.rb +4 -4
- data/lib/fog/google/requests/sql/update_instance.rb +2 -2
- data/lib/fog/google/shared.rb +10 -5
- data/lib/fog/google/version.rb +1 -1
- data/lib/fog/storage/google_json.rb +4 -0
- data/lib/fog/storage/google_json/mock.rb +6 -0
- data/lib/fog/storage/google_json/models/directories.rb +1 -1
- data/lib/fog/storage/google_json/models/directory.rb +1 -1
- data/lib/fog/storage/google_json/models/file.rb +1 -1
- data/lib/fog/storage/google_json/models/files.rb +1 -1
- data/lib/fog/storage/google_json/real.rb +106 -3
- data/lib/fog/storage/google_json/requests/copy_object.rb +12 -1
- data/lib/fog/storage/google_json/requests/get_object.rb +5 -3
- data/lib/fog/storage/google_json/requests/list_buckets.rb +4 -4
- data/lib/fog/storage/google_json/requests/list_objects.rb +1 -1
- data/lib/fog/storage/google_json/requests/put_bucket.rb +1 -1
- data/lib/fog/storage/google_json/requests/put_bucket_acl.rb +1 -1
- data/lib/fog/storage/google_json/requests/put_object.rb +1 -1
- data/lib/fog/storage/google_json/requests/put_object_acl.rb +1 -1
- data/lib/fog/storage/google_json/utils.rb +6 -2
- data/lib/fog/storage/google_xml/models/file.rb +2 -2
- data/lib/fog/storage/google_xml/requests/get_bucket.rb +0 -1
- data/lib/fog/storage/google_xml/requests/head_object.rb +7 -6
- data/tasks/changelog.rake +10 -1
- data/test/helpers/integration_test_helper.rb +15 -1
- data/test/integration/monitoring/test_metric_descriptors.rb +1 -1
- data/test/integration/monitoring/test_timeseries.rb +11 -25
- data/test/integration/pubsub/test_pubsub_models.rb +3 -3
- data/test/integration/pubsub/test_pubsub_requests.rb +2 -2
- data/test/integration/sql/test_certs.rb +0 -1
- data/test/integration/storage/test_objects.rb +36 -0
- data/test/unit/storage/test_common_xml_collections.rb +11 -0
- data/test/unit/storage/test_json_requests.rb +8 -0
- metadata +28 -13
- data/.travis.yml +0 -16
@@ -13,7 +13,14 @@ module Fog
|
|
13
13
|
options[:google_api_scope_url] = GOOGLE_STORAGE_JSON_API_SCOPE_URLS.join(" ")
|
14
14
|
@host = options[:host] || "storage.googleapis.com"
|
15
15
|
|
16
|
+
# TODO(temikus): Do we even need this client?
|
16
17
|
@client = initialize_google_client(options)
|
18
|
+
# IAM client used for SignBlob API
|
19
|
+
@iam_service = ::Google::Apis::IamcredentialsV1::IAMCredentialsService.new
|
20
|
+
apply_client_options(@iam_service, {
|
21
|
+
google_api_scope_url: GOOGLE_STORAGE_JSON_IAM_API_SCOPE_URLS.join(" ")
|
22
|
+
})
|
23
|
+
|
17
24
|
@storage_json = ::Google::Apis::StorageV1::StorageService.new
|
18
25
|
apply_client_options(@storage_json, options)
|
19
26
|
|
@@ -56,12 +63,108 @@ DATA
|
|
56
63
|
canonical_resource.chop!
|
57
64
|
string_to_sign << canonical_resource.to_s
|
58
65
|
|
59
|
-
|
60
|
-
|
61
|
-
|
66
|
+
# TODO(temikus): make signer configurable or add ability to supply your own via lambda
|
67
|
+
if !@storage_json.authorization.signing_key.nil?
|
68
|
+
signed_string = default_signer(string_to_sign)
|
69
|
+
else
|
70
|
+
# If client doesn't contain signing key attempt to auth via IAM SignBlob API
|
71
|
+
signed_string = iam_signer(string_to_sign)
|
72
|
+
end
|
62
73
|
|
63
74
|
Base64.encode64(signed_string).chomp!
|
64
75
|
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def google_access_id
|
80
|
+
@google_access_id ||= get_google_access_id
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Fetches the google service account name
|
85
|
+
#
|
86
|
+
# @return [String] Service account name, typically needed for GoogleAccessId, e.g.
|
87
|
+
# my-account@project.iam.gserviceaccount
|
88
|
+
# @raises [Fog::Errors::Error] If authorisation is incorrect or inapplicable for current action
|
89
|
+
def get_google_access_id
|
90
|
+
if @storage_json.authorization.is_a?(::Google::Auth::UserRefreshCredentials)
|
91
|
+
raise Fog::Errors::Error.new("User / Application Default Credentials are not supported for storage"\
|
92
|
+
"url signing, please use a service account or metadata authentication.")
|
93
|
+
end
|
94
|
+
|
95
|
+
if !@storage_json.authorization.issuer.nil?
|
96
|
+
return @storage_json.authorization.issuer
|
97
|
+
else
|
98
|
+
get_access_id_from_metadata
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Attempts to fetch the google service account name from metadata using Google::Cloud::Env
|
104
|
+
#
|
105
|
+
# @return [String] Service account name, typically needed for GoogleAccessId, e.g.
|
106
|
+
# my-account@project.iam.gserviceaccount
|
107
|
+
# @raises [Fog::Errors::Error] If Metadata service is not available or returns an invalid response
|
108
|
+
def get_access_id_from_metadata
|
109
|
+
if @google_cloud_env.metadata?
|
110
|
+
access_id = @google_cloud_env.lookup_metadata("instance", "service-accounts/default/email")
|
111
|
+
else
|
112
|
+
raise Fog::Errors::Error.new("Metadata service not available, unable to retrieve service account info.")
|
113
|
+
end
|
114
|
+
|
115
|
+
if access_id.nil?
|
116
|
+
raise Fog::Errors::Error.new("Metadata service found but didn't return data." \
|
117
|
+
"Please file a bug: https://github.com/fog/fog-google")
|
118
|
+
end
|
119
|
+
|
120
|
+
return access_id
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Default url signer using service account keys
|
125
|
+
#
|
126
|
+
# @param [String] string_to_sign Special collection of headers and options for V2 storage signing, e.g.:
|
127
|
+
#
|
128
|
+
# StringToSign = HTTP_Verb + "\n" +
|
129
|
+
# Content_MD5 + "\n" +
|
130
|
+
# Content_Type + "\n" +
|
131
|
+
# Expires + "\n" +
|
132
|
+
# Canonicalized_Extension_Headers +
|
133
|
+
# Canonicalized_Resource
|
134
|
+
#
|
135
|
+
# See https://cloud.google.com/storage/docs/access-control/signed-urls-v2
|
136
|
+
# @return [String] Signature binary blob
|
137
|
+
def default_signer(string_to_sign)
|
138
|
+
key = OpenSSL::PKey::RSA.new(@storage_json.authorization.signing_key)
|
139
|
+
digest = OpenSSL::Digest::SHA256.new
|
140
|
+
return key.sign(digest, string_to_sign)
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Fallback URL signer using the IAM SignServiceAccountBlob API, see
|
145
|
+
# Google::Apis::IamcredentialsV1::IAMCredentialsService#sign_service_account_blob
|
146
|
+
#
|
147
|
+
# @param [String] string_to_sign Special collection of headers and options for V2 storage signing, e.g.:
|
148
|
+
#
|
149
|
+
# StringToSign = HTTP_Verb + "\n" +
|
150
|
+
# Content_MD5 + "\n" +
|
151
|
+
# Content_Type + "\n" +
|
152
|
+
# Expires + "\n" +
|
153
|
+
# Canonicalized_Extension_Headers +
|
154
|
+
# Canonicalized_Resource
|
155
|
+
#
|
156
|
+
# See https://cloud.google.com/storage/docs/access-control/signed-urls-v2
|
157
|
+
# @return [String] Signature binary blob
|
158
|
+
def iam_signer(string_to_sign)
|
159
|
+
request = {
|
160
|
+
"payload": string_to_sign
|
161
|
+
}
|
162
|
+
|
163
|
+
resource = "projects/-/serviceAccounts/#{google_access_id}"
|
164
|
+
response = @iam_service.sign_service_account_blob resource, request, {}
|
165
|
+
|
166
|
+
return response.signed_blob
|
167
|
+
end
|
65
168
|
end
|
66
169
|
end
|
67
170
|
end
|
@@ -14,9 +14,20 @@ module Fog
|
|
14
14
|
def copy_object(source_bucket, source_object,
|
15
15
|
target_bucket, target_object, options = {})
|
16
16
|
request_options = ::Google::Apis::RequestOptions.default.merge(options)
|
17
|
+
|
18
|
+
object = ::Google::Apis::StorageV1::Object.new(**options)
|
19
|
+
|
17
20
|
@storage_json.copy_object(source_bucket, source_object,
|
18
21
|
target_bucket, target_object,
|
19
|
-
request_options)
|
22
|
+
object, options: request_options, **filter_keyword_args(options))
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def filter_keyword_args(options)
|
28
|
+
method = @storage_json.method(:copy_object)
|
29
|
+
allowed = method.parameters.filter { |param| %i(key keyreq).include?(param[0]) }.map { |param| param[1] }.compact
|
30
|
+
options.filter { |key, _| allowed.include?(key) }
|
20
31
|
end
|
21
32
|
end
|
22
33
|
|
@@ -39,6 +39,7 @@ module Fog
|
|
39
39
|
raise ArgumentError.new("object_name is required") unless object_name
|
40
40
|
|
41
41
|
buf = Tempfile.new("fog-google-storage-temp")
|
42
|
+
buf.unlink
|
42
43
|
|
43
44
|
# Two requests are necessary, first for metadata, then for content.
|
44
45
|
# google-api-ruby-client doesn't allow fetching both metadata and content
|
@@ -53,18 +54,19 @@ module Fog
|
|
53
54
|
:options => request_options
|
54
55
|
}
|
55
56
|
|
56
|
-
object = @storage_json.get_object(bucket_name, object_name, all_opts).to_h
|
57
|
+
object = @storage_json.get_object(bucket_name, object_name, **all_opts).to_h
|
57
58
|
@storage_json.get_object(
|
58
59
|
bucket_name,
|
59
60
|
object_name,
|
60
|
-
all_opts.merge(:download_dest => buf
|
61
|
+
**all_opts.merge(:download_dest => buf)
|
61
62
|
)
|
62
63
|
|
64
|
+
buf.seek(0)
|
65
|
+
|
63
66
|
if block_given?
|
64
67
|
yield buf.read, nil, nil
|
65
68
|
else
|
66
69
|
object[:body] = buf.read
|
67
|
-
buf.unlink
|
68
70
|
end
|
69
71
|
|
70
72
|
object
|
@@ -11,10 +11,10 @@ module Fog
|
|
11
11
|
prefix: nil, projection: nil)
|
12
12
|
@storage_json.list_buckets(
|
13
13
|
@project,
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
14
|
+
max_results: max_results,
|
15
|
+
page_token: page_token,
|
16
|
+
prefix: prefix,
|
17
|
+
projection: projection
|
18
18
|
)
|
19
19
|
end
|
20
20
|
end
|
@@ -12,7 +12,7 @@ module Fog
|
|
12
12
|
raise ArgumentError.new("bucket_name is required") unless bucket_name
|
13
13
|
raise ArgumentError.new("acl is required") unless acl
|
14
14
|
|
15
|
-
acl_update = ::Google::Apis::StorageV1::BucketAccessControl.new(acl)
|
15
|
+
acl_update = ::Google::Apis::StorageV1::BucketAccessControl.new(**acl)
|
16
16
|
@storage_json.insert_bucket_access_control(bucket_name, acl_update)
|
17
17
|
end
|
18
18
|
end
|
@@ -15,7 +15,7 @@ module Fog
|
|
15
15
|
raise ArgumentError.new("object_name is required") unless object_name
|
16
16
|
raise ArgumentError.new("acl is required") unless acl
|
17
17
|
|
18
|
-
acl_object = ::Google::Apis::StorageV1::ObjectAccessControl.new(acl)
|
18
|
+
acl_object = ::Google::Apis::StorageV1::ObjectAccessControl.new(**acl)
|
19
19
|
|
20
20
|
@storage_json.insert_object_access_control(
|
21
21
|
bucket_name, object_name, acl_object
|
@@ -19,7 +19,11 @@ module Fog
|
|
19
19
|
|
20
20
|
def host_path_query(params, expires)
|
21
21
|
params[:headers]["Date"] = expires.to_i
|
22
|
-
|
22
|
+
# implementation from CGI.escape, but without ' ' to '+' conversion
|
23
|
+
params[:path] = params[:path].b.gsub(/([^a-zA-Z0-9_.\-~]+)/) { |m|
|
24
|
+
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
|
25
|
+
}.gsub("%2F", "/")
|
26
|
+
|
23
27
|
query = []
|
24
28
|
|
25
29
|
if params[:query]
|
@@ -27,7 +31,7 @@ module Fog
|
|
27
31
|
query = filtered.map { |k, v| [k.to_s, Fog::Google.escape(v)].join("=") }
|
28
32
|
end
|
29
33
|
|
30
|
-
query << "GoogleAccessId=#{
|
34
|
+
query << "GoogleAccessId=#{google_access_id}"
|
31
35
|
query << "Signature=#{CGI.escape(signature(params))}"
|
32
36
|
query << "Expires=#{params[:headers]['Date']}"
|
33
37
|
"#{params[:host]}/#{params[:path]}?#{query.join('&')}"
|
@@ -51,7 +51,7 @@ module Fog
|
|
51
51
|
|
52
52
|
remove_method :metadata
|
53
53
|
def metadata
|
54
|
-
attributes.
|
54
|
+
attributes.select { |key, _value| key.to_s =~ /^x-goog-meta-/ }
|
55
55
|
end
|
56
56
|
|
57
57
|
remove_method :metadata=
|
@@ -109,7 +109,7 @@ module Fog
|
|
109
109
|
options["Expires"] = expires if expires
|
110
110
|
options.merge!(metadata)
|
111
111
|
|
112
|
-
data = service.put_object(directory.key, key, body, options)
|
112
|
+
data = service.put_object(directory.key, key, body, **options)
|
113
113
|
merge_attributes(data.headers.reject { |key, _value| ["Content-Length", "Content-Type"].include?(key) })
|
114
114
|
self.content_length = Fog::Storage.get_body_size(body)
|
115
115
|
self.content_type ||= Fog::Storage.get_content_type(body)
|
@@ -33,12 +33,13 @@ module Fog
|
|
33
33
|
headers["If-Modified-Since"] = Fog::Time.at(options["If-Modified-Since"].to_i).to_date_header if options["If-Modified-Since"]
|
34
34
|
headers["If-Unmodified-Since"] = Fog::Time.at(options["If-Unmodified-Since"].to_i).to_date_header if options["If-Modified-Since"]
|
35
35
|
headers.merge!(options)
|
36
|
-
request(:expects
|
37
|
-
:headers
|
38
|
-
:host
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
36
|
+
request(:expects => [200, 206],
|
37
|
+
:headers => headers,
|
38
|
+
:host => "#{bucket_name}.#{@host}",
|
39
|
+
:idempotent => true,
|
40
|
+
:method => "HEAD",
|
41
|
+
:path => Fog::Google.escape(object_name),
|
42
|
+
:query => query)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
data/tasks/changelog.rake
CHANGED
@@ -20,11 +20,20 @@ end
|
|
20
20
|
|
21
21
|
# Extracts all changes that have been made after the latest pushed tag
|
22
22
|
def changes_since_last_tag
|
23
|
-
`git --no-pager log $(git describe --tags --abbrev=0)..HEAD --
|
23
|
+
`git --no-pager log $(git describe --tags --abbrev=0)..HEAD --grep="Merge" --pretty=format:"%t - %s%n%b%n"`
|
24
|
+
end
|
25
|
+
|
26
|
+
# Extracts all github users contributed since last tag
|
27
|
+
def users_since_last_tag
|
28
|
+
`git --no-pager log $(git describe --tags --abbrev=0)..HEAD --grep="Merge" --pretty=format:"%s" | cut -d' ' -f 6 | cut -d/ -f1 | sort | uniq`
|
24
29
|
end
|
25
30
|
|
26
31
|
namespace :changelog do
|
27
32
|
task :generate do
|
28
33
|
insert_after_line("CHANGELOG.md", changes_since_last_tag, /^## Next/)
|
34
|
+
contributors = users_since_last_tag.split("\n").map { |name| "@" + name }
|
35
|
+
printf("Huge thanks to all our contributors 🎆\n")
|
36
|
+
printf("Special thanks to: " + contributors.join(" ") + "\n")
|
37
|
+
printf("\nI'll merge this and release the gem once all tests pass.\n")
|
29
38
|
end
|
30
39
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "helpers/test_helper"
|
2
2
|
require "helpers/test_collection"
|
3
|
+
require "retriable"
|
3
4
|
|
4
5
|
# Use :test credentials in ~/.fog for live integration testing
|
5
6
|
# XXX not sure if this will work on Travis CI or not
|
@@ -22,7 +23,7 @@ TEST_IMAGE_FAMILY = "debian-9".freeze
|
|
22
23
|
|
23
24
|
# XXX This depends on a public image in gs://fog-test-bucket; there may be a better way to do this
|
24
25
|
# The image was created like so: https://cloud.google.com/compute/docs/images#export_an_image_to_google_cloud_storage
|
25
|
-
TEST_RAW_DISK_SOURCE = "
|
26
|
+
TEST_RAW_DISK_SOURCE = "https://storage.googleapis.com/fog-testing-bucket/fog-test-raw-disk-source.image.tar.gz".freeze
|
26
27
|
|
27
28
|
TEST_SQL_TIER = "db-n1-standard-1".freeze
|
28
29
|
TEST_SQL_REGION = TEST_REGION
|
@@ -87,8 +88,21 @@ wLjafhPTSAIS0jijglJ7uzaSbFUW11fw1/EIqIFNe0R0Xf9lsyPxFA==
|
|
87
88
|
-----END RSA PRIVATE KEY-----
|
88
89
|
KEY
|
89
90
|
|
91
|
+
# Retry module config - standard retriable gem settings
|
92
|
+
# see: https://github.com/kamui/retriable
|
93
|
+
RETRIABLE_TRIES = 3
|
94
|
+
RETRIABLE_BASE_INTERVAL = 50
|
95
|
+
|
90
96
|
class FogIntegrationTest < MiniTest::Test
|
91
97
|
def namespaced_name
|
92
98
|
"#{self.class}_#{name}"
|
93
99
|
end
|
100
|
+
|
101
|
+
def retry_on(klass)
|
102
|
+
Retriable.retriable(on: klass,
|
103
|
+
tries: RETRIABLE_TRIES,
|
104
|
+
base_interval: RETRIABLE_BASE_INTERVAL) do
|
105
|
+
yield
|
106
|
+
end
|
107
|
+
end
|
94
108
|
end
|
@@ -68,7 +68,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
68
68
|
:labels => [label]
|
69
69
|
}
|
70
70
|
|
71
|
-
created = @client.create_metric_descriptor(options)
|
71
|
+
created = @client.create_metric_descriptor(**options)
|
72
72
|
|
73
73
|
# Check created metric descriptor
|
74
74
|
assert_equal(_full_name(metric_type), created.name)
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require "helpers/integration_test_helper"
|
2
|
-
require "retriable"
|
3
2
|
|
4
3
|
class TestMetricDescriptors < FogIntegrationTest
|
5
|
-
#
|
6
|
-
# metric propagation (sometimes 80+ seconds) and client
|
7
|
-
# Google::Apis::ClientError: badRequest if the metric
|
8
|
-
|
9
|
-
|
4
|
+
# This module has a decent amount of retry wrappers as the Stackdriver API
|
5
|
+
# can be quite slow with metric propagation (sometimes 80+ seconds) and client
|
6
|
+
# returning errors, e.g. Google::Apis::ClientError: badRequest if the metric
|
7
|
+
# hasn't yet been created instead of a 404.
|
8
|
+
|
10
9
|
TEST_METRIC_PREFIX = "custom.googleapis.com/fog-google-test/timeseries".freeze
|
11
10
|
LABEL_DESCRIPTORS = [
|
12
11
|
{
|
@@ -51,10 +50,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
51
50
|
assert_empty(resp.to_h)
|
52
51
|
|
53
52
|
# Wait for metric to be created
|
54
|
-
|
55
|
-
Retriable.retriable(on: Google::Apis::ClientError,
|
56
|
-
tries: RETRIABLE_TRIES,
|
57
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
53
|
+
retry_on(Google::Apis::ClientError) do
|
58
54
|
@client.list_timeseries(
|
59
55
|
:filter => "metric.type = \"#{metric_type}\"",
|
60
56
|
:interval => {
|
@@ -67,9 +63,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
67
63
|
).time_series
|
68
64
|
end
|
69
65
|
|
70
|
-
series =
|
71
|
-
tries: RETRIABLE_TRIES,
|
72
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
66
|
+
series = retry_on(Google::Apis::ClientError) do
|
73
67
|
@client.timeseries_collection.all(
|
74
68
|
:filter => "metric.type = \"#{metric_type}\"",
|
75
69
|
:interval => {
|
@@ -115,9 +109,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
115
109
|
_some_timeseries(start_time, metric_type, labels)
|
116
110
|
end
|
117
111
|
|
118
|
-
|
119
|
-
tries: RETRIABLE_TRIES,
|
120
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
112
|
+
retry_on(Google::Apis::ServerError) do
|
121
113
|
@client.create_timeseries(:timeseries => timeseries)
|
122
114
|
end
|
123
115
|
interval = {
|
@@ -132,9 +124,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
132
124
|
# Wait for metric to be created
|
133
125
|
# Retriable is used instead of wait_for due to API client returning Google::Apis::ClientError: badRequest if the
|
134
126
|
# metric hasn't yet been created
|
135
|
-
|
136
|
-
tries: RETRIABLE_TRIES,
|
137
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
127
|
+
retry_on(Google::Apis::ClientError) do
|
138
128
|
@client.list_timeseries(
|
139
129
|
:filter => "metric.type = \"#{metric_type}\"",
|
140
130
|
:interval => interval
|
@@ -142,9 +132,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
142
132
|
end
|
143
133
|
|
144
134
|
# Test page size
|
145
|
-
resp =
|
146
|
-
tries: RETRIABLE_TRIES,
|
147
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
135
|
+
resp = retry_on(Google::Apis::ClientError) do
|
148
136
|
@client.list_timeseries(
|
149
137
|
:filter => "metric.type = \"#{metric_type}\"",
|
150
138
|
:interval => interval,
|
@@ -170,9 +158,7 @@ class TestMetricDescriptors < FogIntegrationTest
|
|
170
158
|
"expected different timeseries when using page_token")
|
171
159
|
|
172
160
|
# Test filter
|
173
|
-
series =
|
174
|
-
tries: RETRIABLE_TRIES,
|
175
|
-
base_interval: RETRIABLE_BASE_INTERVAL) do
|
161
|
+
series = retry_on(Google::Apis::ClientError) do
|
176
162
|
@client.timeseries_collection.all(
|
177
163
|
:filter => %[
|
178
164
|
metric.type = "#{metric_type}" AND
|