gcloud 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/AUTHENTICATION.md +3 -3
- data/CHANGELOG.md +92 -0
- data/OVERVIEW.md +3 -3
- data/lib/gcloud.rb +75 -25
- data/lib/gcloud/backoff.rb +5 -1
- data/lib/gcloud/bigquery.rb +25 -43
- data/lib/gcloud/bigquery/copy_job.rb +13 -13
- data/lib/gcloud/bigquery/data.rb +20 -16
- data/lib/gcloud/bigquery/dataset.rb +202 -177
- data/lib/gcloud/bigquery/dataset/access.rb +118 -104
- data/lib/gcloud/bigquery/dataset/list.rb +14 -18
- data/lib/gcloud/bigquery/extract_job.rb +12 -12
- data/lib/gcloud/bigquery/insert_response.rb +12 -14
- data/lib/gcloud/bigquery/job.rb +45 -57
- data/lib/gcloud/bigquery/job/list.rb +18 -24
- data/lib/gcloud/bigquery/load_job.rb +35 -27
- data/lib/gcloud/bigquery/project.rb +53 -73
- data/lib/gcloud/bigquery/query_data.rb +28 -35
- data/lib/gcloud/bigquery/query_job.rb +18 -18
- data/lib/gcloud/bigquery/schema.rb +359 -0
- data/lib/gcloud/bigquery/service.rb +506 -0
- data/lib/gcloud/bigquery/table.rb +185 -266
- data/lib/gcloud/bigquery/table/list.rb +15 -19
- data/lib/gcloud/bigquery/view.rb +126 -81
- data/lib/gcloud/datastore.rb +39 -27
- data/lib/gcloud/datastore/commit.rb +2 -2
- data/lib/gcloud/datastore/dataset.rb +8 -19
- data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -4
- data/lib/gcloud/datastore/dataset/query_results.rb +0 -2
- data/lib/gcloud/datastore/entity.rb +7 -1
- data/lib/gcloud/datastore/errors.rb +5 -27
- data/lib/gcloud/datastore/grpc_utils.rb +4 -3
- data/lib/gcloud/datastore/key.rb +6 -0
- data/lib/gcloud/datastore/service.rb +18 -12
- data/lib/gcloud/datastore/transaction.rb +0 -10
- data/lib/gcloud/dns.rb +29 -19
- data/lib/gcloud/dns/change.rb +10 -15
- data/lib/gcloud/dns/change/list.rb +4 -4
- data/lib/gcloud/dns/importer.rb +1 -1
- data/lib/gcloud/dns/project.rb +32 -49
- data/lib/gcloud/dns/record.rb +8 -2
- data/lib/gcloud/dns/record/list.rb +4 -4
- data/lib/gcloud/dns/service.rb +167 -0
- data/lib/gcloud/dns/zone.rb +33 -52
- data/lib/gcloud/dns/zone/list.rb +12 -16
- data/lib/gcloud/errors.rb +31 -19
- data/lib/gcloud/logging.rb +50 -39
- data/lib/gcloud/logging/entry.rb +197 -24
- data/lib/gcloud/logging/entry/list.rb +0 -2
- data/lib/gcloud/logging/logger.rb +1 -1
- data/lib/gcloud/logging/metric.rb +3 -9
- data/lib/gcloud/logging/metric/list.rb +0 -2
- data/lib/gcloud/logging/project.rb +58 -54
- data/lib/gcloud/logging/resource_descriptor.rb +2 -2
- data/lib/gcloud/logging/resource_descriptor/list.rb +0 -2
- data/lib/gcloud/logging/service.rb +32 -23
- data/lib/gcloud/logging/sink.rb +8 -14
- data/lib/gcloud/logging/sink/list.rb +0 -2
- data/lib/gcloud/pubsub.rb +21 -16
- data/lib/gcloud/pubsub/policy.rb +204 -0
- data/lib/gcloud/pubsub/project.rb +26 -38
- data/lib/gcloud/pubsub/service.rb +39 -31
- data/lib/gcloud/pubsub/subscription.rb +56 -59
- data/lib/gcloud/pubsub/subscription/list.rb +4 -4
- data/lib/gcloud/pubsub/topic.rb +69 -66
- data/lib/gcloud/pubsub/topic/list.rb +0 -2
- data/lib/gcloud/pubsub/topic/{batch.rb → publisher.rb} +15 -2
- data/lib/gcloud/resource_manager.rb +27 -26
- data/lib/gcloud/resource_manager/manager.rb +19 -39
- data/lib/gcloud/resource_manager/policy.rb +211 -0
- data/lib/gcloud/resource_manager/project.rb +97 -121
- data/lib/gcloud/resource_manager/project/list.rb +7 -7
- data/lib/gcloud/resource_manager/project/updater.rb +4 -9
- data/lib/gcloud/resource_manager/service.rb +127 -0
- data/lib/gcloud/storage.rb +24 -42
- data/lib/gcloud/storage/bucket.rb +104 -192
- data/lib/gcloud/storage/bucket/acl.rb +47 -143
- data/lib/gcloud/storage/bucket/cors.rb +55 -11
- data/lib/gcloud/storage/bucket/list.rb +14 -14
- data/lib/gcloud/storage/errors.rb +3 -43
- data/lib/gcloud/storage/file.rb +114 -111
- data/lib/gcloud/storage/file/acl.rb +27 -113
- data/lib/gcloud/storage/file/list.rb +21 -21
- data/lib/gcloud/storage/project.rb +49 -59
- data/lib/gcloud/storage/service.rb +347 -0
- data/lib/gcloud/translate.rb +24 -14
- data/lib/gcloud/translate/api.rb +12 -21
- data/lib/gcloud/translate/detection.rb +5 -5
- data/lib/gcloud/translate/language.rb +1 -1
- data/lib/gcloud/translate/service.rb +80 -0
- data/lib/gcloud/translate/translation.rb +6 -6
- data/lib/gcloud/version.rb +1 -1
- data/lib/gcloud/vision.rb +24 -15
- data/lib/gcloud/vision/annotate.rb +24 -21
- data/lib/gcloud/vision/annotation.rb +9 -9
- data/lib/gcloud/vision/annotation/entity.rb +11 -11
- data/lib/gcloud/vision/annotation/face.rb +25 -25
- data/lib/gcloud/vision/annotation/properties.rb +8 -8
- data/lib/gcloud/vision/annotation/safe_search.rb +4 -4
- data/lib/gcloud/vision/annotation/text.rb +7 -7
- data/lib/gcloud/vision/annotation/vertex.rb +1 -1
- data/lib/gcloud/vision/image.rb +11 -11
- data/lib/gcloud/vision/location.rb +5 -2
- data/lib/gcloud/vision/project.rb +14 -16
- data/lib/gcloud/vision/service.rb +66 -0
- data/lib/google/api_client.rb +0 -0
- metadata +27 -24
- data/lib/gcloud/bigquery/connection.rb +0 -624
- data/lib/gcloud/bigquery/errors.rb +0 -68
- data/lib/gcloud/bigquery/table/schema.rb +0 -234
- data/lib/gcloud/dns/connection.rb +0 -173
- data/lib/gcloud/dns/errors.rb +0 -68
- data/lib/gcloud/resource_manager/connection.rb +0 -134
- data/lib/gcloud/resource_manager/errors.rb +0 -68
- data/lib/gcloud/storage/connection.rb +0 -444
- data/lib/gcloud/translate/connection.rb +0 -85
- data/lib/gcloud/translate/errors.rb +0 -68
- data/lib/gcloud/upload.rb +0 -95
- data/lib/gcloud/vision/connection.rb +0 -63
- data/lib/gcloud/vision/errors.rb +0 -69
@@ -143,14 +143,14 @@ module Gcloud
|
|
143
143
|
|
144
144
|
##
|
145
145
|
# @private New Projects::List from a response object.
|
146
|
-
def self.
|
147
|
-
projects = new(Array(
|
148
|
-
Project.from_gapi gapi_object, manager.
|
146
|
+
def self.from_gapi gapi_list, manager, filter = nil, max = nil
|
147
|
+
projects = new(Array(gapi_list.projects).map do |gapi_object|
|
148
|
+
Project.from_gapi gapi_object, manager.service
|
149
149
|
end)
|
150
|
-
projects.instance_variable_set
|
151
|
-
projects.instance_variable_set
|
152
|
-
projects.instance_variable_set
|
153
|
-
projects.instance_variable_set
|
150
|
+
projects.instance_variable_set :@token, gapi_list.next_page_token
|
151
|
+
projects.instance_variable_set :@manager, manager
|
152
|
+
projects.instance_variable_set :@filter, filter
|
153
|
+
projects.instance_variable_set :@max, max
|
154
154
|
projects
|
155
155
|
end
|
156
156
|
|
@@ -14,7 +14,6 @@
|
|
14
14
|
|
15
15
|
|
16
16
|
require "time"
|
17
|
-
require "gcloud/resource_manager/errors"
|
18
17
|
|
19
18
|
module Gcloud
|
20
19
|
module ResourceManager
|
@@ -61,7 +60,7 @@ module Gcloud
|
|
61
60
|
# end
|
62
61
|
#
|
63
62
|
def name= new_name
|
64
|
-
gapi
|
63
|
+
gapi.name = new_name
|
65
64
|
end
|
66
65
|
|
67
66
|
##
|
@@ -88,7 +87,7 @@ module Gcloud
|
|
88
87
|
# end
|
89
88
|
#
|
90
89
|
def labels
|
91
|
-
gapi
|
90
|
+
gapi.labels
|
92
91
|
end
|
93
92
|
|
94
93
|
##
|
@@ -115,17 +114,13 @@ module Gcloud
|
|
115
114
|
# end
|
116
115
|
#
|
117
116
|
def labels= new_labels
|
118
|
-
gapi
|
117
|
+
gapi.labels = new_labels
|
119
118
|
end
|
120
119
|
|
121
120
|
##
|
122
121
|
# @private Create an Updater object.
|
123
122
|
def self.from_project project
|
124
|
-
dupe_gapi = project.gapi.
|
125
|
-
dupe_gapi = dupe_gapi.to_hash if dupe_gapi.respond_to? :to_hash
|
126
|
-
if dupe_gapi["labels"].respond_to? :to_hash
|
127
|
-
dupe_gapi["labels"] = dupe_gapi["labels"].to_hash
|
128
|
-
end
|
123
|
+
dupe_gapi = project.gapi.class.new project.gapi.to_h
|
129
124
|
dupe_project = Project.from_gapi dupe_gapi, nil # no way to update
|
130
125
|
Updater.new dupe_project
|
131
126
|
end
|
@@ -0,0 +1,127 @@
|
|
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 "gcloud/version"
|
17
|
+
require "gcloud/errors"
|
18
|
+
require "google/apis/cloudresourcemanager_v1"
|
19
|
+
|
20
|
+
module Gcloud
|
21
|
+
module ResourceManager
|
22
|
+
##
|
23
|
+
# @private
|
24
|
+
# Represents the service to Resource Manager, as well as expose the API
|
25
|
+
# calls.
|
26
|
+
class Service
|
27
|
+
##
|
28
|
+
# Alias to the Google Client API module
|
29
|
+
API = Google::Apis::CloudresourcemanagerV1
|
30
|
+
|
31
|
+
attr_accessor :credentials
|
32
|
+
|
33
|
+
##
|
34
|
+
# Creates a new Service instance.
|
35
|
+
def initialize credentials, retries: nil, timeout: nil
|
36
|
+
@credentials = credentials
|
37
|
+
@service = API::CloudResourceManagerService.new
|
38
|
+
@service.client_options.application_name = "gcloud-ruby"
|
39
|
+
@service.client_options.application_version = Gcloud::VERSION
|
40
|
+
@service.request_options.retries = retries || 3
|
41
|
+
@service.request_options.timeout_sec = timeout if timeout
|
42
|
+
@service.authorization = @credentials.client
|
43
|
+
end
|
44
|
+
|
45
|
+
def service
|
46
|
+
return mocked_service if mocked_service
|
47
|
+
@service
|
48
|
+
end
|
49
|
+
attr_accessor :mocked_service
|
50
|
+
|
51
|
+
##
|
52
|
+
# Returns API::ListProjectsResponse
|
53
|
+
def list_project filter: nil, token: nil, max: nil
|
54
|
+
service.list_projects page_token: token, page_size: max, filter: filter
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Returns API::Project
|
59
|
+
def get_project project_id
|
60
|
+
service.get_project project_id
|
61
|
+
rescue Google::Apis::Error => e
|
62
|
+
raise Gcloud::Error.from_error(e)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns API::Project
|
67
|
+
def create_project project_id, name, labels
|
68
|
+
project_attrs = { projectId: project_id, name: name,
|
69
|
+
labels: labels }.delete_if { |_, v| v.nil? }
|
70
|
+
service.create_project API::Project.new(project_attrs)
|
71
|
+
rescue Google::Apis::Error => e
|
72
|
+
raise Gcloud::Error.from_error(e)
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Updated the project, given a API::Project.
|
77
|
+
# Returns API::Project
|
78
|
+
def update_project project_gapi
|
79
|
+
service.update_project project_gapi.project_id, project_gapi
|
80
|
+
rescue Google::Apis::Error => e
|
81
|
+
raise Gcloud::Error.from_error(e)
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete_project project_id
|
85
|
+
service.delete_project project_id
|
86
|
+
rescue Google::Apis::Error => e
|
87
|
+
raise Gcloud::Error.from_error(e)
|
88
|
+
end
|
89
|
+
|
90
|
+
def undelete_project project_id
|
91
|
+
service.undelete_project project_id
|
92
|
+
rescue Google::Apis::Error => e
|
93
|
+
raise Gcloud::Error.from_error(e)
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Returns API::Policy
|
98
|
+
def get_policy project_id
|
99
|
+
service.get_project_iam_policy "projects/#{project_id}"
|
100
|
+
rescue Google::Apis::Error => e
|
101
|
+
raise Gcloud::Error.from_error(e)
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Returns API::Policy
|
106
|
+
def set_policy project_id, new_policy
|
107
|
+
req = API::SetIamPolicyRequest.new policy: new_policy
|
108
|
+
service.set_project_iam_policy "projects/#{project_id}", req
|
109
|
+
rescue Google::Apis::Error => e
|
110
|
+
raise Gcloud::Error.from_error(e)
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Returns API::TestIamPermissionsResponse
|
115
|
+
def test_permissions project_id, permissions
|
116
|
+
req = API::TestIamPermissionsRequest.new permissions: permissions
|
117
|
+
service.test_project_iam_permissions "projects/#{project_id}", req
|
118
|
+
rescue Google::Apis::Error => e
|
119
|
+
raise Gcloud::Error.from_error(e)
|
120
|
+
end
|
121
|
+
|
122
|
+
def inspect
|
123
|
+
"#{self.class}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/gcloud/storage.rb
CHANGED
@@ -36,6 +36,9 @@ module Gcloud
|
|
36
36
|
# The default scope is:
|
37
37
|
#
|
38
38
|
# * `https://www.googleapis.com/auth/devstorage.full_control`
|
39
|
+
# @param [Integer] retries Number of times to retry requests on server error.
|
40
|
+
# The default value is `3`. Optional.
|
41
|
+
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
39
42
|
#
|
40
43
|
# @return [Gcloud::Storage::Project]
|
41
44
|
#
|
@@ -48,14 +51,21 @@ module Gcloud
|
|
48
51
|
# bucket = storage.bucket "my-bucket"
|
49
52
|
# file = bucket.file "path/to/my-file.ext"
|
50
53
|
#
|
51
|
-
def self.storage project = nil, keyfile = nil, scope: nil
|
54
|
+
def self.storage project = nil, keyfile = nil, scope: nil, retries: nil,
|
55
|
+
timeout: nil
|
52
56
|
project ||= Gcloud::Storage::Project.default_project
|
57
|
+
project = project.to_s # Always cast to a string
|
58
|
+
fail ArgumentError, "project is missing" if project.empty?
|
59
|
+
|
53
60
|
if keyfile.nil?
|
54
61
|
credentials = Gcloud::Storage::Credentials.default scope: scope
|
55
62
|
else
|
56
63
|
credentials = Gcloud::Storage::Credentials.new keyfile, scope: scope
|
57
64
|
end
|
58
|
-
|
65
|
+
|
66
|
+
Gcloud::Storage::Project.new(
|
67
|
+
Gcloud::Storage::Service.new(
|
68
|
+
project, credentials, retries: retries, timeout: timeout))
|
59
69
|
end
|
60
70
|
|
61
71
|
##
|
@@ -66,7 +76,7 @@ module Gcloud
|
|
66
76
|
# time, taking advantage of Google's own reliable and fast networking
|
67
77
|
# infrastructure to perform data operations in a cost effective manner.
|
68
78
|
#
|
69
|
-
#
|
79
|
+
# The goal of gcloud-ruby is to provide a API that is comfortable to
|
70
80
|
# Rubyists. Authentication is handled by {Gcloud#storage}. You can provide the
|
71
81
|
# project and credential information to connect to the Storage service, or if
|
72
82
|
# you are running on Google Compute Engine this configuration is taken care
|
@@ -279,33 +289,6 @@ module Gcloud
|
|
279
289
|
# encryption_key_sha256: key_hash
|
280
290
|
# ```
|
281
291
|
#
|
282
|
-
# ### A note about large uploads
|
283
|
-
#
|
284
|
-
# You may encounter a Broken pipe (Errno::EPIPE) error when attempting to
|
285
|
-
# upload large files. To avoid this problem, add the
|
286
|
-
# [httpclient](https://rubygems.org/gems/httpclient) gem to your project, and
|
287
|
-
# the line (or lines) of configuration shown below. These lines must execute
|
288
|
-
# after you require gcloud but before you make your first gcloud connection.
|
289
|
-
# The first statement configures [Faraday](https://rubygems.org/gems/faraday)
|
290
|
-
# to use httpclient. The second statement, which should only be added if you
|
291
|
-
# are using a version of Faraday at or above 0.9.2, is a workaround for [this
|
292
|
-
# gzip issue](https://github.com/GoogleCloudPlatform/gcloud-ruby/issues/367).
|
293
|
-
#
|
294
|
-
# ```ruby
|
295
|
-
# require "gcloud"
|
296
|
-
#
|
297
|
-
# # Use httpclient to avoid broken pipe errors with large uploads
|
298
|
-
# Faraday.default_adapter = :httpclient
|
299
|
-
#
|
300
|
-
# # Only add the following statement if using Faraday >= 0.9.2
|
301
|
-
# # Override gzip middleware with no-op for httpclient
|
302
|
-
# Faraday::Response.register_middleware :gzip =>
|
303
|
-
# Faraday::Response::Middleware
|
304
|
-
#
|
305
|
-
# gcloud = Gcloud.new
|
306
|
-
# storage = gcloud.storage
|
307
|
-
# ```
|
308
|
-
#
|
309
292
|
# ## Downloading a File
|
310
293
|
#
|
311
294
|
# Files can be downloaded to the local file system. (See
|
@@ -444,24 +427,23 @@ module Gcloud
|
|
444
427
|
# file.acl.public!
|
445
428
|
# ```
|
446
429
|
#
|
447
|
-
# ## Configuring
|
430
|
+
# ## Configuring retries and timeout
|
448
431
|
#
|
449
|
-
#
|
450
|
-
#
|
451
|
-
#
|
452
|
-
# `
|
432
|
+
# You can configure how many times API requests may be automatically retried.
|
433
|
+
# When an API request fails, the response will be inspected to see if the
|
434
|
+
# request meets criteria indicating that it may succeed on retry, such as
|
435
|
+
# `500` and `503` status codes or a specific internal error code such as
|
436
|
+
# `rateLimitExceeded`. If it meets the criteria, the request will be retried
|
437
|
+
# after a delay. If another error occurs, the delay will be increased before a
|
438
|
+
# subsequent attempt, until the `retries` limit is reached.
|
453
439
|
#
|
454
|
-
#
|
455
|
-
# should be retried. If the response matches the criteria, then the request
|
456
|
-
# will be retried after a delay. If another error occurs, the delay will be
|
457
|
-
# increased incrementally before a subsequent attempt. The first retry will be
|
458
|
-
# delayed one second, the second retry two seconds, and so on.
|
440
|
+
# You can also set the request `timeout` value in seconds.
|
459
441
|
#
|
460
442
|
# ```ruby
|
461
443
|
# require "gcloud"
|
462
|
-
# require "gcloud/backoff"
|
463
444
|
#
|
464
|
-
#
|
445
|
+
# gcloud = Gcloud.new
|
446
|
+
# storage = gcloud.storage retries: 10, timeout: 120
|
465
447
|
# ```
|
466
448
|
#
|
467
449
|
# See the [Storage status and error
|
@@ -17,7 +17,7 @@ require "gcloud/storage/bucket/acl"
|
|
17
17
|
require "gcloud/storage/bucket/list"
|
18
18
|
require "gcloud/storage/bucket/cors"
|
19
19
|
require "gcloud/storage/file"
|
20
|
-
require "
|
20
|
+
require "pathname"
|
21
21
|
|
22
22
|
module Gcloud
|
23
23
|
module Storage
|
@@ -37,8 +37,8 @@ module Gcloud
|
|
37
37
|
#
|
38
38
|
class Bucket
|
39
39
|
##
|
40
|
-
# @private The
|
41
|
-
attr_accessor :
|
40
|
+
# @private The Service object.
|
41
|
+
attr_accessor :service
|
42
42
|
|
43
43
|
##
|
44
44
|
# @private The Google API Client object.
|
@@ -47,39 +47,39 @@ module Gcloud
|
|
47
47
|
##
|
48
48
|
# @private Create an empty Bucket object.
|
49
49
|
def initialize
|
50
|
-
@
|
51
|
-
@gapi =
|
50
|
+
@service = nil
|
51
|
+
@gapi = Google::Apis::StorageV1::Bucket.new
|
52
52
|
end
|
53
53
|
|
54
54
|
##
|
55
55
|
# The kind of item this is.
|
56
56
|
# For buckets, this is always `storage#bucket`.
|
57
57
|
def kind
|
58
|
-
@gapi
|
58
|
+
@gapi.kind
|
59
59
|
end
|
60
60
|
|
61
61
|
##
|
62
62
|
# The ID of the bucket.
|
63
63
|
def id
|
64
|
-
@gapi
|
64
|
+
@gapi.id
|
65
65
|
end
|
66
66
|
|
67
67
|
##
|
68
68
|
# The name of the bucket.
|
69
69
|
def name
|
70
|
-
@gapi
|
70
|
+
@gapi.name
|
71
71
|
end
|
72
72
|
|
73
73
|
##
|
74
74
|
# A URL that can be used to access the bucket using the REST API.
|
75
75
|
def api_url
|
76
|
-
@gapi
|
76
|
+
@gapi.self_link
|
77
77
|
end
|
78
78
|
|
79
79
|
##
|
80
80
|
# Creation time of the bucket.
|
81
81
|
def created_at
|
82
|
-
@gapi
|
82
|
+
@gapi.time_created
|
83
83
|
end
|
84
84
|
|
85
85
|
##
|
@@ -128,26 +128,15 @@ module Gcloud
|
|
128
128
|
# end
|
129
129
|
#
|
130
130
|
def cors
|
131
|
+
cors_builder = Bucket::Cors.from_gapi @gapi.cors_configurations
|
131
132
|
if block_given?
|
132
|
-
cors_builder = Bucket::Cors.new @gapi["cors"]
|
133
133
|
yield cors_builder
|
134
|
-
|
134
|
+
if cors_builder.changed?
|
135
|
+
@gapi.cors_configurations = cors_builder.to_gapi
|
136
|
+
patch_gapi! :cors_configurations
|
137
|
+
end
|
135
138
|
end
|
136
|
-
|
137
|
-
end
|
138
|
-
|
139
|
-
##
|
140
|
-
# Updates the CORS configuration for a static website served from the
|
141
|
-
# bucket.
|
142
|
-
#
|
143
|
-
# Accepts an array of hashes containing the attributes specified for the
|
144
|
-
# [resource description of
|
145
|
-
# cors](https://cloud.google.com/storage/docs/json_api/v1/buckets#cors).
|
146
|
-
#
|
147
|
-
# @see https://cloud.google.com/storage/docs/cross-origin Cross-Origin
|
148
|
-
# Resource Sharing (CORS)
|
149
|
-
def cors= new_cors
|
150
|
-
patch_gapi! cors: new_cors
|
139
|
+
cors_builder.freeze # always return frozen objects
|
151
140
|
end
|
152
141
|
|
153
142
|
##
|
@@ -158,7 +147,7 @@ module Gcloud
|
|
158
147
|
#
|
159
148
|
# @see https://cloud.google.com/storage/docs/concepts-techniques
|
160
149
|
def location
|
161
|
-
@gapi
|
150
|
+
@gapi.location
|
162
151
|
end
|
163
152
|
|
164
153
|
##
|
@@ -167,7 +156,7 @@ module Gcloud
|
|
167
156
|
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
168
157
|
#
|
169
158
|
def logging_bucket
|
170
|
-
@gapi
|
159
|
+
@gapi.logging.log_bucket if @gapi.logging
|
171
160
|
end
|
172
161
|
|
173
162
|
##
|
@@ -178,7 +167,9 @@ module Gcloud
|
|
178
167
|
# @param [String] logging_bucket The bucket to hold the logging output
|
179
168
|
#
|
180
169
|
def logging_bucket= logging_bucket
|
181
|
-
|
170
|
+
@gapi.logging ||= Google::Apis::StorageV1::Bucket::Logging.new
|
171
|
+
@gapi.logging.log_bucket = logging_bucket
|
172
|
+
patch_gapi! :logging
|
182
173
|
end
|
183
174
|
|
184
175
|
##
|
@@ -187,7 +178,7 @@ module Gcloud
|
|
187
178
|
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
188
179
|
#
|
189
180
|
def logging_prefix
|
190
|
-
@gapi
|
181
|
+
@gapi.logging.log_object_prefix if @gapi.logging
|
191
182
|
end
|
192
183
|
|
193
184
|
##
|
@@ -201,7 +192,9 @@ module Gcloud
|
|
201
192
|
# @see https://cloud.google.com/storage/docs/access-logs Access Logs
|
202
193
|
#
|
203
194
|
def logging_prefix= logging_prefix
|
204
|
-
|
195
|
+
@gapi.logging ||= Google::Apis::StorageV1::Bucket::Logging.new
|
196
|
+
@gapi.logging.log_object_prefix = logging_prefix
|
197
|
+
patch_gapi! :logging
|
205
198
|
end
|
206
199
|
|
207
200
|
##
|
@@ -209,7 +202,7 @@ module Gcloud
|
|
209
202
|
# stored and determines the SLA and the cost of storage. Values include
|
210
203
|
# `STANDARD`, `NEARLINE`, and `DURABLE_REDUCED_AVAILABILITY`.
|
211
204
|
def storage_class
|
212
|
-
@gapi
|
205
|
+
@gapi.storage_class
|
213
206
|
end
|
214
207
|
|
215
208
|
##
|
@@ -217,7 +210,7 @@ module Gcloud
|
|
217
210
|
# Versioning](https://cloud.google.com/storage/docs/object-versioning) is
|
218
211
|
# enabled for the bucket.
|
219
212
|
def versioning?
|
220
|
-
|
213
|
+
@gapi.versioning.enabled? unless @gapi.versioning.nil?
|
221
214
|
end
|
222
215
|
|
223
216
|
##
|
@@ -228,7 +221,9 @@ module Gcloud
|
|
228
221
|
# @return [Boolean]
|
229
222
|
#
|
230
223
|
def versioning= new_versioning
|
231
|
-
|
224
|
+
@gapi.versioning ||= Google::Apis::StorageV1::Bucket::Versioning.new
|
225
|
+
@gapi.versioning.enabled = new_versioning
|
226
|
+
patch_gapi! :versioning
|
232
227
|
end
|
233
228
|
|
234
229
|
##
|
@@ -239,7 +234,7 @@ module Gcloud
|
|
239
234
|
# How to Host a Static Website
|
240
235
|
#
|
241
236
|
def website_main
|
242
|
-
@gapi
|
237
|
+
@gapi.website.main_page_suffix if @gapi.website
|
243
238
|
end
|
244
239
|
|
245
240
|
##
|
@@ -250,7 +245,9 @@ module Gcloud
|
|
250
245
|
# How to Host a Static Website
|
251
246
|
#
|
252
247
|
def website_main= website_main
|
253
|
-
|
248
|
+
@gapi.website ||= Google::Apis::StorageV1::Bucket::Website.new
|
249
|
+
@gapi.website.main_page_suffix = website_main
|
250
|
+
patch_gapi! :website
|
254
251
|
end
|
255
252
|
|
256
253
|
##
|
@@ -261,7 +258,7 @@ module Gcloud
|
|
261
258
|
# How to Host a Static Website
|
262
259
|
#
|
263
260
|
def website_404
|
264
|
-
@gapi
|
261
|
+
@gapi.website.not_found_page if @gapi.website
|
265
262
|
end
|
266
263
|
|
267
264
|
##
|
@@ -272,12 +269,14 @@ module Gcloud
|
|
272
269
|
# How to Host a Static Website
|
273
270
|
#
|
274
271
|
def website_404= website_404
|
275
|
-
|
272
|
+
@gapi.website ||= Google::Apis::StorageV1::Bucket::Website.new
|
273
|
+
@gapi.website.not_found_page = website_404
|
274
|
+
patch_gapi! :website
|
276
275
|
end
|
277
276
|
|
278
277
|
##
|
279
278
|
# Updates the bucket with changes made in the given block in a single
|
280
|
-
# PATCH request. The following attributes may be set: {#cors
|
279
|
+
# PATCH request. The following attributes may be set: {#cors},
|
281
280
|
# {#logging_bucket=}, {#logging_prefix=}, {#versioning=},
|
282
281
|
# {#website_main=}, and {#website_404=}. In addition, the #cors
|
283
282
|
# configuration accessible in the block is completely mutable and will be
|
@@ -316,8 +315,10 @@ module Gcloud
|
|
316
315
|
# end
|
317
316
|
#
|
318
317
|
def update
|
319
|
-
updater = Updater.new @gapi
|
318
|
+
updater = Updater.new @gapi
|
320
319
|
yield updater
|
320
|
+
# Add check for mutable cors
|
321
|
+
updater.check_for_mutable_cors!
|
321
322
|
patch_gapi! updater.updates unless updater.updates.empty?
|
322
323
|
end
|
323
324
|
|
@@ -326,7 +327,7 @@ module Gcloud
|
|
326
327
|
# The bucket must be empty before it can be deleted.
|
327
328
|
#
|
328
329
|
# The API call to delete the bucket may be retried under certain
|
329
|
-
# conditions. See {Gcloud
|
330
|
+
# conditions. See {Gcloud#storage} to control this behavior.
|
330
331
|
#
|
331
332
|
# @return [Boolean] Returns `true` if the bucket was deleted.
|
332
333
|
#
|
@@ -340,13 +341,9 @@ module Gcloud
|
|
340
341
|
# bucket.delete
|
341
342
|
#
|
342
343
|
def delete
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
true
|
347
|
-
else
|
348
|
-
fail ApiError.from_response(resp)
|
349
|
-
end
|
344
|
+
ensure_service!
|
345
|
+
service.delete_bucket name
|
346
|
+
true
|
350
347
|
end
|
351
348
|
|
352
349
|
##
|
@@ -398,7 +395,7 @@ module Gcloud
|
|
398
395
|
# end
|
399
396
|
#
|
400
397
|
def files prefix: nil, delimiter: nil, token: nil, max: nil, versions: nil
|
401
|
-
|
398
|
+
ensure_service!
|
402
399
|
options = {
|
403
400
|
prefix: prefix,
|
404
401
|
delimiter: delimiter,
|
@@ -406,10 +403,9 @@ module Gcloud
|
|
406
403
|
max: max,
|
407
404
|
versions: versions
|
408
405
|
}
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
versions
|
406
|
+
gapi = service.list_files name, options
|
407
|
+
File::List.from_gapi gapi, service, name, prefix, delimiter, max,
|
408
|
+
versions
|
413
409
|
end
|
414
410
|
alias_method :find_files, :files
|
415
411
|
|
@@ -449,15 +445,13 @@ module Gcloud
|
|
449
445
|
#
|
450
446
|
def file path, generation: nil, encryption_key: nil,
|
451
447
|
encryption_key_sha256: nil
|
452
|
-
|
453
|
-
options = { generation: generation,
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
fail ApiError.from_response(resp)
|
460
|
-
end
|
448
|
+
ensure_service!
|
449
|
+
options = { generation: generation, key: encryption_key,
|
450
|
+
key_sha256: encryption_key_sha256 }
|
451
|
+
gapi = service.get_file name, path, options
|
452
|
+
File.from_gapi gapi, service
|
453
|
+
rescue Gcloud::NotFoundError
|
454
|
+
nil
|
461
455
|
end
|
462
456
|
alias_method :find_file, :file
|
463
457
|
|
@@ -465,12 +459,6 @@ module Gcloud
|
|
465
459
|
# Creates a new {File} object by providing a path to a local file to
|
466
460
|
# upload and the path to store it with in the bucket.
|
467
461
|
#
|
468
|
-
# A `chunk_size` value can be provided in the options to be used
|
469
|
-
# in resumable uploads. This value is the number of bytes per
|
470
|
-
# chunk and must be divisible by 256KB. If it is not divisible
|
471
|
-
# by 256KB then it will be lowered to the nearest acceptable
|
472
|
-
# value.
|
473
|
-
#
|
474
462
|
# #### Customer-supplied encryption keys
|
475
463
|
#
|
476
464
|
# By default, Google Cloud Storage manages server-side encryption keys on
|
@@ -485,29 +473,6 @@ module Gcloud
|
|
485
473
|
# files and buckets are also not encrypted, and you can read or update the
|
486
474
|
# metadata of an encrypted file without providing the encryption key.
|
487
475
|
#
|
488
|
-
# #### Troubleshooting large uploads
|
489
|
-
#
|
490
|
-
# You may encounter errors while attempting to upload large files. Below
|
491
|
-
# are a couple of common cases and their solutions.
|
492
|
-
#
|
493
|
-
# ##### Handling memory errors
|
494
|
-
#
|
495
|
-
# If you encounter a memory error such as `NoMemoryError`, try performing
|
496
|
-
# a resumable upload and setting the `chunk_size` option to a value that
|
497
|
-
# works for your environment, as explained in the final example above.
|
498
|
-
#
|
499
|
-
# ##### Handling broken pipe errors
|
500
|
-
#
|
501
|
-
# To avoid broken pipe (`Errno::EPIPE`) errors when uploading, add the
|
502
|
-
# [httpclient](https://rubygems.org/gems/httpclient) gem to your project,
|
503
|
-
# and the configuration shown below. These lines must execute after you
|
504
|
-
# require gcloud but before you make your first gcloud connection. The
|
505
|
-
# first statement configures [Faraday](https://rubygems.org/gems/faraday)
|
506
|
-
# to use httpclient. The second statement, which should only be added if
|
507
|
-
# you are using a version of Faraday at or above 0.9.2, is a workaround
|
508
|
-
# for [this gzip
|
509
|
-
# issue](https://github.com/GoogleCloudPlatform/gcloud-ruby/issues/367).
|
510
|
-
#
|
511
476
|
# @param [String] file Path of the file on the filesystem to upload.
|
512
477
|
# @param [String] path Path to store the file in Google Cloud Storage.
|
513
478
|
# @param [String] acl A predefined set of access controls to apply to this
|
@@ -542,10 +507,6 @@ module Gcloud
|
|
542
507
|
# @param [String] content_type The
|
543
508
|
# [Content-Type](https://tools.ietf.org/html/rfc2616#section-14.17)
|
544
509
|
# response header to be returned when the file is downloaded.
|
545
|
-
# @param [Integer] chunk_size The number of bytes per chunk in a resumable
|
546
|
-
# upload. Must be divisible by 256KB. If it is not divisible by 265KB
|
547
|
-
# then it will be lowered to the nearest acceptable value. If no value
|
548
|
-
# is provided it will use {Gcloud::Upload.default_chunk_size}. Optional.
|
549
510
|
# @param [String] crc32c The CRC32c checksum of the file data, as
|
550
511
|
# described in [RFC 4960, Appendix
|
551
512
|
# B](http://tools.ietf.org/html/rfc4960#appendix-B).
|
@@ -591,18 +552,6 @@ module Gcloud
|
|
591
552
|
# bucket.create_file "path/to/local.file.ext",
|
592
553
|
# "destination/path/file.ext"
|
593
554
|
#
|
594
|
-
# @example Specifying the chunk size as a number of bytes:
|
595
|
-
# require "gcloud"
|
596
|
-
#
|
597
|
-
# gcloud = Gcloud.new
|
598
|
-
# storage = gcloud.storage
|
599
|
-
#
|
600
|
-
# bucket = storage.bucket "my-bucket"
|
601
|
-
#
|
602
|
-
# bucket.create_file "path/to/local.file.ext",
|
603
|
-
# "destination/path/file.ext",
|
604
|
-
# chunk_size: 1024*1024 # 1 MB chunk
|
605
|
-
#
|
606
555
|
# @example Providing a customer-supplied encryption key:
|
607
556
|
# require "gcloud"
|
608
557
|
# require "digest/sha2"
|
@@ -627,39 +576,23 @@ module Gcloud
|
|
627
576
|
# encryption_key: key,
|
628
577
|
# encryption_key_sha256: key_hash
|
629
578
|
#
|
630
|
-
# @example Avoiding broken pipe errors with large uploads:
|
631
|
-
# require "gcloud"
|
632
|
-
#
|
633
|
-
# # Use httpclient to avoid broken pipe errors with large uploads
|
634
|
-
# Faraday.default_adapter = :httpclient
|
635
|
-
#
|
636
|
-
# # Only add the following statement if using Faraday >= 0.9.2
|
637
|
-
# # Override gzip middleware with no-op for httpclient
|
638
|
-
# Faraday::Response.register_middleware :gzip =>
|
639
|
-
# Faraday::Response::Middleware
|
640
|
-
#
|
641
|
-
# gcloud = Gcloud.new
|
642
|
-
# storage = gcloud.storage
|
643
|
-
#
|
644
579
|
def create_file file, path = nil, acl: nil, cache_control: nil,
|
645
580
|
content_disposition: nil, content_encoding: nil,
|
646
|
-
content_language: nil, content_type: nil,
|
581
|
+
content_language: nil, content_type: nil,
|
647
582
|
crc32c: nil, md5: nil, metadata: nil, encryption_key: nil,
|
648
583
|
encryption_key_sha256: nil
|
649
|
-
|
584
|
+
ensure_service!
|
650
585
|
options = { acl: File::Acl.predefined_rule_for(acl), md5: md5,
|
651
586
|
cache_control: cache_control, content_type: content_type,
|
652
587
|
content_disposition: content_disposition, crc32c: crc32c,
|
653
|
-
content_encoding: content_encoding,
|
588
|
+
content_encoding: content_encoding,
|
654
589
|
content_language: content_language, metadata: metadata,
|
655
|
-
|
656
|
-
encryption_key_sha256: encryption_key_sha256 }
|
590
|
+
key: encryption_key, key_sha256: encryption_key_sha256 }
|
657
591
|
ensure_file_exists! file
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
fail ApiError.from_response(resp)
|
592
|
+
# TODO: Handle file as an IO and path is missing more gracefully
|
593
|
+
path ||= Pathname(file).to_path
|
594
|
+
gapi = service.insert_file name, file, path, options
|
595
|
+
File.from_gapi gapi, service
|
663
596
|
end
|
664
597
|
alias_method :upload_file, :create_file
|
665
598
|
alias_method :new_file, :create_file
|
@@ -760,13 +693,8 @@ module Gcloud
|
|
760
693
|
##
|
761
694
|
# Reloads the bucket with current data from the Storage service.
|
762
695
|
def reload!
|
763
|
-
|
764
|
-
|
765
|
-
if resp.success?
|
766
|
-
@gapi = resp.data
|
767
|
-
else
|
768
|
-
fail ApiError.from_response(resp)
|
769
|
-
end
|
696
|
+
ensure_service!
|
697
|
+
@gapi = service.get_bucket name
|
770
698
|
end
|
771
699
|
alias_method :refresh!, :reload!
|
772
700
|
|
@@ -775,26 +703,27 @@ module Gcloud
|
|
775
703
|
def self.from_gapi gapi, conn
|
776
704
|
new.tap do |f|
|
777
705
|
f.gapi = gapi
|
778
|
-
f.
|
706
|
+
f.service = conn
|
779
707
|
end
|
780
708
|
end
|
781
709
|
|
782
710
|
protected
|
783
711
|
|
784
712
|
##
|
785
|
-
# Raise an error unless an active
|
786
|
-
def
|
787
|
-
fail "Must have active connection" unless
|
713
|
+
# Raise an error unless an active service is available.
|
714
|
+
def ensure_service!
|
715
|
+
fail "Must have active connection" unless service
|
788
716
|
end
|
789
717
|
|
790
|
-
def patch_gapi!
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
718
|
+
def patch_gapi! *attributes
|
719
|
+
attributes.flatten!
|
720
|
+
return if attributes.empty?
|
721
|
+
ensure_service!
|
722
|
+
patch_args = Hash[attributes.map do |attr|
|
723
|
+
[attr, @gapi.send(attr)]
|
724
|
+
end]
|
725
|
+
patch_gapi = Google::Apis::StorageV1::Bucket.new patch_args
|
726
|
+
@gapi = service.patch_bucket name, patch_gapi
|
798
727
|
end
|
799
728
|
|
800
729
|
##
|
@@ -804,58 +733,41 @@ module Gcloud
|
|
804
733
|
fail ArgumentError, "cannot find file #{file}"
|
805
734
|
end
|
806
735
|
|
807
|
-
##
|
808
|
-
# @private Determines if a resumable upload should be used.
|
809
|
-
def resumable_upload? file
|
810
|
-
::File.size?(file).to_i > Upload.resumable_threshold
|
811
|
-
end
|
812
|
-
|
813
|
-
##
|
814
|
-
# Given nil, empty array, a gapi array of hashes, or any value, returns a
|
815
|
-
# deeply dup'd and frozen array of simple hashes or values (not gapi
|
816
|
-
# objects.)
|
817
|
-
def deep_dup_and_freeze array
|
818
|
-
return [].freeze if array.nil? || array.empty?
|
819
|
-
array = Array(array.dup)
|
820
|
-
array = array.map do |h|
|
821
|
-
h = h.to_hash if h.respond_to? :to_hash
|
822
|
-
h.dup.freeze
|
823
|
-
end
|
824
|
-
array.freeze
|
825
|
-
end
|
826
|
-
|
827
736
|
##
|
828
737
|
# Yielded to a block to accumulate changes for a patch request.
|
829
|
-
class Updater
|
738
|
+
class Updater < Bucket
|
830
739
|
attr_reader :updates
|
831
740
|
##
|
832
741
|
# Create an Updater object.
|
833
|
-
def initialize
|
834
|
-
@
|
835
|
-
@
|
836
|
-
@
|
742
|
+
def initialize gapi
|
743
|
+
@updates = []
|
744
|
+
@gapi = gapi
|
745
|
+
@cors_builder = nil
|
837
746
|
end
|
838
747
|
|
839
|
-
|
840
|
-
|
748
|
+
def cors
|
749
|
+
# Same as Bucket#cors, but not frozen
|
750
|
+
@cors_builder ||= Bucket::Cors.from_gapi @gapi.cors_configurations
|
751
|
+
yield @cors_builder if block_given?
|
752
|
+
@cors_builder
|
753
|
+
end
|
841
754
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
755
|
+
##
|
756
|
+
# @private Make sure any cors changes are saved
|
757
|
+
def check_for_mutable_cors!
|
758
|
+
return if @cors_builder.nil?
|
759
|
+
return unless @cors_builder.changed?
|
760
|
+
@gapi.cors_configurations = @cors_builder.to_gapi
|
761
|
+
patch_gapi! :cors_configurations
|
846
762
|
end
|
847
763
|
|
764
|
+
protected
|
765
|
+
|
848
766
|
##
|
849
|
-
#
|
850
|
-
|
851
|
-
|
852
|
-
updates
|
853
|
-
if block_given?
|
854
|
-
cors_builder = Bucket::Cors.new updates[:cors]
|
855
|
-
yield cors_builder
|
856
|
-
updates[:cors] = cors_builder if cors_builder.changed?
|
857
|
-
end
|
858
|
-
updates[:cors]
|
767
|
+
# Queue up all the updates instead of making them.
|
768
|
+
def patch_gapi! attribute
|
769
|
+
@updates << attribute
|
770
|
+
@updates.uniq!
|
859
771
|
end
|
860
772
|
end
|
861
773
|
end
|