gcloud 0.11.0 → 0.12.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.
Files changed (121) hide show
  1. checksums.yaml +8 -8
  2. data/AUTHENTICATION.md +3 -3
  3. data/CHANGELOG.md +92 -0
  4. data/OVERVIEW.md +3 -3
  5. data/lib/gcloud.rb +75 -25
  6. data/lib/gcloud/backoff.rb +5 -1
  7. data/lib/gcloud/bigquery.rb +25 -43
  8. data/lib/gcloud/bigquery/copy_job.rb +13 -13
  9. data/lib/gcloud/bigquery/data.rb +20 -16
  10. data/lib/gcloud/bigquery/dataset.rb +202 -177
  11. data/lib/gcloud/bigquery/dataset/access.rb +118 -104
  12. data/lib/gcloud/bigquery/dataset/list.rb +14 -18
  13. data/lib/gcloud/bigquery/extract_job.rb +12 -12
  14. data/lib/gcloud/bigquery/insert_response.rb +12 -14
  15. data/lib/gcloud/bigquery/job.rb +45 -57
  16. data/lib/gcloud/bigquery/job/list.rb +18 -24
  17. data/lib/gcloud/bigquery/load_job.rb +35 -27
  18. data/lib/gcloud/bigquery/project.rb +53 -73
  19. data/lib/gcloud/bigquery/query_data.rb +28 -35
  20. data/lib/gcloud/bigquery/query_job.rb +18 -18
  21. data/lib/gcloud/bigquery/schema.rb +359 -0
  22. data/lib/gcloud/bigquery/service.rb +506 -0
  23. data/lib/gcloud/bigquery/table.rb +185 -266
  24. data/lib/gcloud/bigquery/table/list.rb +15 -19
  25. data/lib/gcloud/bigquery/view.rb +126 -81
  26. data/lib/gcloud/datastore.rb +39 -27
  27. data/lib/gcloud/datastore/commit.rb +2 -2
  28. data/lib/gcloud/datastore/dataset.rb +8 -19
  29. data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -4
  30. data/lib/gcloud/datastore/dataset/query_results.rb +0 -2
  31. data/lib/gcloud/datastore/entity.rb +7 -1
  32. data/lib/gcloud/datastore/errors.rb +5 -27
  33. data/lib/gcloud/datastore/grpc_utils.rb +4 -3
  34. data/lib/gcloud/datastore/key.rb +6 -0
  35. data/lib/gcloud/datastore/service.rb +18 -12
  36. data/lib/gcloud/datastore/transaction.rb +0 -10
  37. data/lib/gcloud/dns.rb +29 -19
  38. data/lib/gcloud/dns/change.rb +10 -15
  39. data/lib/gcloud/dns/change/list.rb +4 -4
  40. data/lib/gcloud/dns/importer.rb +1 -1
  41. data/lib/gcloud/dns/project.rb +32 -49
  42. data/lib/gcloud/dns/record.rb +8 -2
  43. data/lib/gcloud/dns/record/list.rb +4 -4
  44. data/lib/gcloud/dns/service.rb +167 -0
  45. data/lib/gcloud/dns/zone.rb +33 -52
  46. data/lib/gcloud/dns/zone/list.rb +12 -16
  47. data/lib/gcloud/errors.rb +31 -19
  48. data/lib/gcloud/logging.rb +50 -39
  49. data/lib/gcloud/logging/entry.rb +197 -24
  50. data/lib/gcloud/logging/entry/list.rb +0 -2
  51. data/lib/gcloud/logging/logger.rb +1 -1
  52. data/lib/gcloud/logging/metric.rb +3 -9
  53. data/lib/gcloud/logging/metric/list.rb +0 -2
  54. data/lib/gcloud/logging/project.rb +58 -54
  55. data/lib/gcloud/logging/resource_descriptor.rb +2 -2
  56. data/lib/gcloud/logging/resource_descriptor/list.rb +0 -2
  57. data/lib/gcloud/logging/service.rb +32 -23
  58. data/lib/gcloud/logging/sink.rb +8 -14
  59. data/lib/gcloud/logging/sink/list.rb +0 -2
  60. data/lib/gcloud/pubsub.rb +21 -16
  61. data/lib/gcloud/pubsub/policy.rb +204 -0
  62. data/lib/gcloud/pubsub/project.rb +26 -38
  63. data/lib/gcloud/pubsub/service.rb +39 -31
  64. data/lib/gcloud/pubsub/subscription.rb +56 -59
  65. data/lib/gcloud/pubsub/subscription/list.rb +4 -4
  66. data/lib/gcloud/pubsub/topic.rb +69 -66
  67. data/lib/gcloud/pubsub/topic/list.rb +0 -2
  68. data/lib/gcloud/pubsub/topic/{batch.rb → publisher.rb} +15 -2
  69. data/lib/gcloud/resource_manager.rb +27 -26
  70. data/lib/gcloud/resource_manager/manager.rb +19 -39
  71. data/lib/gcloud/resource_manager/policy.rb +211 -0
  72. data/lib/gcloud/resource_manager/project.rb +97 -121
  73. data/lib/gcloud/resource_manager/project/list.rb +7 -7
  74. data/lib/gcloud/resource_manager/project/updater.rb +4 -9
  75. data/lib/gcloud/resource_manager/service.rb +127 -0
  76. data/lib/gcloud/storage.rb +24 -42
  77. data/lib/gcloud/storage/bucket.rb +104 -192
  78. data/lib/gcloud/storage/bucket/acl.rb +47 -143
  79. data/lib/gcloud/storage/bucket/cors.rb +55 -11
  80. data/lib/gcloud/storage/bucket/list.rb +14 -14
  81. data/lib/gcloud/storage/errors.rb +3 -43
  82. data/lib/gcloud/storage/file.rb +114 -111
  83. data/lib/gcloud/storage/file/acl.rb +27 -113
  84. data/lib/gcloud/storage/file/list.rb +21 -21
  85. data/lib/gcloud/storage/project.rb +49 -59
  86. data/lib/gcloud/storage/service.rb +347 -0
  87. data/lib/gcloud/translate.rb +24 -14
  88. data/lib/gcloud/translate/api.rb +12 -21
  89. data/lib/gcloud/translate/detection.rb +5 -5
  90. data/lib/gcloud/translate/language.rb +1 -1
  91. data/lib/gcloud/translate/service.rb +80 -0
  92. data/lib/gcloud/translate/translation.rb +6 -6
  93. data/lib/gcloud/version.rb +1 -1
  94. data/lib/gcloud/vision.rb +24 -15
  95. data/lib/gcloud/vision/annotate.rb +24 -21
  96. data/lib/gcloud/vision/annotation.rb +9 -9
  97. data/lib/gcloud/vision/annotation/entity.rb +11 -11
  98. data/lib/gcloud/vision/annotation/face.rb +25 -25
  99. data/lib/gcloud/vision/annotation/properties.rb +8 -8
  100. data/lib/gcloud/vision/annotation/safe_search.rb +4 -4
  101. data/lib/gcloud/vision/annotation/text.rb +7 -7
  102. data/lib/gcloud/vision/annotation/vertex.rb +1 -1
  103. data/lib/gcloud/vision/image.rb +11 -11
  104. data/lib/gcloud/vision/location.rb +5 -2
  105. data/lib/gcloud/vision/project.rb +14 -16
  106. data/lib/gcloud/vision/service.rb +66 -0
  107. data/lib/google/api_client.rb +0 -0
  108. metadata +27 -24
  109. data/lib/gcloud/bigquery/connection.rb +0 -624
  110. data/lib/gcloud/bigquery/errors.rb +0 -68
  111. data/lib/gcloud/bigquery/table/schema.rb +0 -234
  112. data/lib/gcloud/dns/connection.rb +0 -173
  113. data/lib/gcloud/dns/errors.rb +0 -68
  114. data/lib/gcloud/resource_manager/connection.rb +0 -134
  115. data/lib/gcloud/resource_manager/errors.rb +0 -68
  116. data/lib/gcloud/storage/connection.rb +0 -444
  117. data/lib/gcloud/translate/connection.rb +0 -85
  118. data/lib/gcloud/translate/errors.rb +0 -68
  119. data/lib/gcloud/upload.rb +0 -95
  120. data/lib/gcloud/vision/connection.rb +0 -63
  121. 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.from_response resp, manager, filter = nil, max = nil
147
- projects = new(Array(resp.data["projects"]).map do |gapi_object|
148
- Project.from_gapi gapi_object, manager.connection
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 "@token", resp.data["nextPageToken"]
151
- projects.instance_variable_set "@manager", manager
152
- projects.instance_variable_set "@filter", filter
153
- projects.instance_variable_set "@max", max
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["name"] = new_name
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["labels"]
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["labels"] = new_labels
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.dup
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
@@ -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
- Gcloud::Storage::Project.new project, credentials
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
- # Gcloud's goal is to provide a API that is familiar and comfortable to
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 Backoff
430
+ # ## Configuring retries and timeout
448
431
  #
449
- # The {Gcloud::Backoff} class allows users to globally configure how Cloud API
450
- # requests are automatically retried in the case of some errors, such as a
451
- # `500` or `503` status code, or a specific internal error code such as
452
- # `rateLimitExceeded`.
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
- # If an API call fails, the response will be inspected to see if the call
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
- # Gcloud::Backoff.retries = 5 # Raise the maximum number of retries from 3
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 "gcloud/upload"
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 Connection object.
41
- attr_accessor :connection
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
- @connection = nil
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["kind"]
58
+ @gapi.kind
59
59
  end
60
60
 
61
61
  ##
62
62
  # The ID of the bucket.
63
63
  def id
64
- @gapi["id"]
64
+ @gapi.id
65
65
  end
66
66
 
67
67
  ##
68
68
  # The name of the bucket.
69
69
  def name
70
- @gapi["name"]
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["selfLink"]
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["timeCreated"]
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
- self.cors = cors_builder if cors_builder.changed?
134
+ if cors_builder.changed?
135
+ @gapi.cors_configurations = cors_builder.to_gapi
136
+ patch_gapi! :cors_configurations
137
+ end
135
138
  end
136
- deep_dup_and_freeze @gapi["cors"]
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["location"]
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["logging"]["logBucket"] if @gapi["logging"]
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
- patch_gapi! logging_bucket: logging_bucket
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["logging"]["logObjectPrefix"] if @gapi["logging"]
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
- patch_gapi! logging_prefix: logging_prefix
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["storageClass"]
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
- !@gapi["versioning"].nil? && @gapi["versioning"]["enabled"]
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
- patch_gapi! versioning: new_versioning
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["website"]["mainPageSuffix"] if @gapi["website"]
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
- patch_gapi! website_main: website_main
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["website"]["notFoundPage"] if @gapi["website"]
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
- patch_gapi! website_404: website_404
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["cors"]
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::Backoff} to control this behavior.
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
- ensure_connection!
344
- resp = connection.delete_bucket name
345
- if resp.success?
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
- ensure_connection!
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
- resp = connection.list_files name, options
410
- fail ApiError.from_response(resp) unless resp.success?
411
- File::List.from_response resp, connection, name, prefix, delimiter, max,
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
- ensure_connection!
453
- options = { generation: generation, encryption_key: encryption_key,
454
- encryption_key_sha256: encryption_key_sha256 }
455
- resp = connection.get_file name, path, options
456
- if resp.success?
457
- File.from_gapi resp.data, connection
458
- else
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, chunk_size: 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
- ensure_connection!
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, chunk_size: chunk_size,
588
+ content_encoding: content_encoding,
654
589
  content_language: content_language, metadata: metadata,
655
- encryption_key: encryption_key,
656
- encryption_key_sha256: encryption_key_sha256 }
590
+ key: encryption_key, key_sha256: encryption_key_sha256 }
657
591
  ensure_file_exists! file
658
- resumable = resumable_upload?(file)
659
- resp = @connection.upload_file resumable, name, file, path, options
660
-
661
- return File.from_gapi(resp.data, connection) if resp.success?
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
- ensure_connection!
764
- resp = connection.get_bucket name
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.connection = conn
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 connection is available.
786
- def ensure_connection!
787
- fail "Must have active connection" unless connection
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! options = {}
791
- ensure_connection!
792
- resp = connection.patch_bucket name, options
793
- if resp.success?
794
- @gapi = resp.data
795
- else
796
- fail ApiError.from_response(resp)
797
- end
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 cors
834
- @cors = cors ? Array(cors.dup) : []
835
- @cors = @cors.map { |x| x.to_hash if x.respond_to? :to_hash }
836
- @updates = {}
742
+ def initialize gapi
743
+ @updates = []
744
+ @gapi = gapi
745
+ @cors_builder = nil
837
746
  end
838
747
 
839
- ATTRS = [:cors, :logging_bucket, :logging_prefix, :versioning,
840
- :website_main, :website_404]
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
- ATTRS.each do |attr|
843
- define_method "#{attr}=" do |arg|
844
- updates[attr] = arg
845
- end
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
- # Return CORS for mutation. Also adds CORS to @updates so that it
850
- # is included in the patch request.
851
- def cors
852
- updates[:cors] ||= @cors
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