gcloud 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,211 @@
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/errors"
17
+ require "google/apis/cloudresourcemanager_v1beta1"
18
+
19
+ module Gcloud
20
+ module ResourceManager
21
+ ##
22
+ # # Policy
23
+ #
24
+ # Represents a Cloud IAM Policy for the Resource Manager service.
25
+ #
26
+ # A common pattern for updating a resource's metadata, such as its Policy,
27
+ # is to read the current data from the service, update the data locally, and
28
+ # then send the modified data for writing. This pattern may result in a
29
+ # conflict if two or more processes attempt the sequence simultaneously. IAM
30
+ # solves this problem with the {Gcloud::ResourceManager::Policy#etag}
31
+ # property, which is used to verify whether the policy has changed since the
32
+ # last request. When you make a request to with an `etag` value, Cloud IAM
33
+ # compares the `etag` value in the request with the existing `etag` value
34
+ # associated with the policy. It writes the policy only if the `etag` values
35
+ # match.
36
+ #
37
+ # When you update a policy, first read the policy (and its current `etag`)
38
+ # from the service, then modify the policy locally, and then write the
39
+ # modified policy to the service. See
40
+ # {Gcloud::ResourceManager::Project#policy} and
41
+ # {Gcloud::ResourceManager::Project#policy=}.
42
+ #
43
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing policies
44
+ # @see https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/setIamPolicy
45
+ # projects.setIamPolicy
46
+ #
47
+ # @attr [String] etag Used to verify whether the policy has changed since
48
+ # the last request. The policy will be written only if the `etag` values
49
+ # match.
50
+ # @attr [Hash{String => Array<String>}] roles The bindings that associate
51
+ # roles with an array of members. See [Understanding
52
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
53
+ # listing of primitive and curated roles.
54
+ # See [Binding](https://cloud.google.com/resource-manager/reference/rpc/google.iam.v1#binding)
55
+ # for a listing of values and patterns for members.
56
+ #
57
+ # @example
58
+ # require "gcloud"
59
+ #
60
+ # gcloud = Gcloud.new
61
+ # resource_manager = gcloud.resource_manager
62
+ # project = resource_manager.project "tokyo-rain-123"
63
+ #
64
+ # policy = project.policy # API call
65
+ #
66
+ # policy.remove "roles/owner", "user:owner@example.com" # Local call
67
+ # policy.add "roles/owner", "user:newowner@example.com" # Local call
68
+ # policy.roles["roles/viewer"] = ["allUsers"] # Local call
69
+ #
70
+ # project.policy = policy # API call
71
+ #
72
+ class Policy
73
+ ##
74
+ # Alias to the Google Client API module
75
+ API = Google::Apis::CloudresourcemanagerV1
76
+
77
+ attr_reader :etag, :roles
78
+
79
+ ##
80
+ # @private Creates a Policy object.
81
+ def initialize etag, roles
82
+ @etag = etag
83
+ @roles = roles
84
+ end
85
+
86
+ ##
87
+ # Convenience method for adding a member to a binding on this policy.
88
+ # See [Understanding
89
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
90
+ # listing of primitive and curated roles.
91
+ # See [Binding](https://cloud.google.com/resource-manager/reference/rpc/google.iam.v1#binding)
92
+ # for a listing of values and patterns for members.
93
+ #
94
+ # @param [String] role_name A Cloud IAM role, such as `"roles/owner"`.
95
+ # @param [String] member A Cloud IAM identity, such as
96
+ # `"user:owner@example.com"`.
97
+ #
98
+ # @example
99
+ # require "gcloud"
100
+ #
101
+ # gcloud = Gcloud.new
102
+ # resource_manager = gcloud.resource_manager
103
+ # project = resource_manager.project "tokyo-rain-123"
104
+ #
105
+ # policy = project.policy # API call
106
+ #
107
+ # policy.add "roles/owner", "user:newowner@example.com" # Local call
108
+ #
109
+ # project.policy = policy # API call
110
+ #
111
+ def add role_name, member
112
+ role(role_name) << member
113
+ end
114
+
115
+ ##
116
+ # Convenience method for removing a member from a binding on this policy.
117
+ # See [Understanding
118
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
119
+ # listing of primitive and curated roles.
120
+ # See [Binding](https://cloud.google.com/resource-manager/reference/rpc/google.iam.v1#binding)
121
+ # for a listing of values and patterns for members.
122
+ #
123
+ # @param [String] role_name A Cloud IAM role, such as `"roles/owner"`.
124
+ # @param [String] member A Cloud IAM identity, such as
125
+ # `"user:owner@example.com"`.
126
+ #
127
+ # @example
128
+ # require "gcloud"
129
+ #
130
+ # gcloud = Gcloud.new
131
+ # resource_manager = gcloud.resource_manager
132
+ # project = resource_manager.project "tokyo-rain-123"
133
+ #
134
+ # policy = project.policy # API call
135
+ #
136
+ # policy.remove "roles/owner", "user:owner@example.com" # Local call
137
+ #
138
+ # project.policy = policy # API call
139
+ #
140
+ def remove role_name, member
141
+ role(role_name).delete member
142
+ end
143
+
144
+ ##
145
+ # Convenience method returning the array of members bound to a role in
146
+ # this policy, or an empty array if no value is present for the role in
147
+ # {#roles}. See [Understanding
148
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
149
+ # listing of primitive and curated roles. See
150
+ # [Binding](https://cloud.google.com/resource-manager/reference/rpc/google.iam.v1#binding)
151
+ # for a listing of values and patterns for members.
152
+ #
153
+ # @return [Array<String>] The members strings, or an empty array.
154
+ #
155
+ # @example
156
+ # require "gcloud"
157
+ #
158
+ # gcloud = Gcloud.new
159
+ # resource_manager = gcloud.resource_manager
160
+ # project = resource_manager.project "tokyo-rain-123"
161
+ #
162
+ # policy = project.policy
163
+ #
164
+ # policy.role("roles/viewer") << "user:viewer@example.com"
165
+ #
166
+ def role role_name
167
+ roles[role_name] ||= []
168
+ end
169
+
170
+ ##
171
+ # Returns a deep copy of the policy.
172
+ #
173
+ # @return [Policy]
174
+ #
175
+ def deep_dup
176
+ dup.tap do |p|
177
+ roles_dup = p.roles.each_with_object({}) do |(k, v), memo|
178
+ memo[k] = v.dup rescue value
179
+ end
180
+ p.instance_variable_set "@roles", roles_dup
181
+ end
182
+ end
183
+
184
+ ##
185
+ # @private Convert the Policy to a
186
+ # Google::Apis::CloudresourcemanagerV1::Policy.
187
+ def to_gapi
188
+ API::Policy.new(
189
+ etag: etag,
190
+ bindings: roles.keys.map do |role_name|
191
+ next if roles[role_name].empty?
192
+ API::Binding.new(
193
+ role: role_name,
194
+ members: roles[role_name]
195
+ )
196
+ end
197
+ )
198
+ end
199
+
200
+ ##
201
+ # @private New Policy from a
202
+ # Google::Apis::CloudresourcemanagerV1::Policy object.
203
+ def self.from_gapi gapi
204
+ roles = gapi.bindings.each_with_object({}) do |binding, memo|
205
+ memo[binding.role] = binding.members.to_a
206
+ end
207
+ new gapi.etag, roles
208
+ end
209
+ end
210
+ end
211
+ end
@@ -14,9 +14,9 @@
14
14
 
15
15
 
16
16
  require "time"
17
- require "gcloud/resource_manager/errors"
18
17
  require "gcloud/resource_manager/project/list"
19
18
  require "gcloud/resource_manager/project/updater"
19
+ require "gcloud/resource_manager/policy"
20
20
 
21
21
  module Gcloud
22
22
  module ResourceManager
@@ -40,8 +40,8 @@ module Gcloud
40
40
  #
41
41
  class Project
42
42
  ##
43
- # @private The Connection object.
44
- attr_accessor :connection
43
+ # @private The Service object.
44
+ attr_accessor :service
45
45
 
46
46
  ##
47
47
  # @private The Google API Client object.
@@ -50,8 +50,8 @@ module Gcloud
50
50
  ##
51
51
  # @private Create an empty Project object.
52
52
  def initialize
53
- @connection = nil
54
- @gapi = {}
53
+ @service = nil
54
+ @gapi = Gcloud::ResourceManager::Service::API::Project.new
55
55
  end
56
56
 
57
57
  ##
@@ -60,21 +60,21 @@ module Gcloud
60
60
  # Trailing hyphens are prohibited. e.g. tokyo-rain-123
61
61
  #
62
62
  def project_id
63
- @gapi["projectId"]
63
+ @gapi.project_id
64
64
  end
65
65
 
66
66
  ##
67
67
  # The number uniquely identifying the project. e.g. 415104041262
68
68
  #
69
69
  def project_number
70
- @gapi["projectNumber"]
70
+ @gapi.project_number
71
71
  end
72
72
 
73
73
  ##
74
74
  # The user-assigned name of the project.
75
75
  #
76
76
  def name
77
- @gapi["name"]
77
+ @gapi.name
78
78
  end
79
79
 
80
80
  ##
@@ -93,14 +93,9 @@ module Gcloud
93
93
  # project.name = "My Project"
94
94
  #
95
95
  def name= new_name
96
- ensure_connection!
97
- @gapi["name"] = new_name
98
- resp = connection.update_project @gapi
99
- if resp.success?
100
- @gapi = resp.data
101
- else
102
- fail ApiError.from_response(resp)
103
- end
96
+ ensure_service!
97
+ @gapi.name = new_name
98
+ @gapi = service.update_project @gapi
104
99
  end
105
100
 
106
101
  ##
@@ -138,8 +133,7 @@ module Gcloud
138
133
  # end
139
134
  #
140
135
  def labels
141
- labels = @gapi["labels"]
142
- labels = labels.to_hash if labels.respond_to? :to_hash
136
+ labels = @gapi.labels.to_h
143
137
  if block_given?
144
138
  yielded_labels = labels.dup
145
139
  yield yielded_labels
@@ -170,21 +164,16 @@ module Gcloud
170
164
  # project.labels = { "env" => "production" }
171
165
  #
172
166
  def labels= new_labels
173
- ensure_connection!
174
- @gapi["labels"] = new_labels
175
- resp = connection.update_project @gapi
176
- if resp.success?
177
- @gapi = resp.data
178
- else
179
- fail ApiError.from_response(resp)
180
- end
167
+ ensure_service!
168
+ @gapi.labels = new_labels
169
+ @gapi = service.update_project @gapi
181
170
  end
182
171
 
183
172
  ##
184
173
  # The time that this project was created.
185
174
  #
186
175
  def created_at
187
- Time.parse @gapi["createTime"]
176
+ Time.parse @gapi.create_time
188
177
  rescue
189
178
  nil
190
179
  end
@@ -194,16 +183,16 @@ module Gcloud
194
183
  #
195
184
  # Possible values are:
196
185
  # * `ACTIVE` - The normal and active state.
197
- # * `LIFECYCLE_STATE_UNSPECIFIED` - Unspecified state. This is only
198
- # used/useful for distinguishing unset values.
199
186
  # * `DELETE_REQUESTED` - The project has been marked for deletion by the
200
- # user (by invoking DeleteProject) or by the system (Google Cloud
201
- # Platform). This can generally be reversed by invoking UndeleteProject.
187
+ # user (by invoking ##delete) or by the system (Google Cloud
188
+ # Platform). This can generally be reversed by invoking {#undelete}.
202
189
  # * `DELETE_IN_PROGRESS` - The process of deleting the project has begun.
203
190
  # Reversing the deletion is no longer possible.
191
+ # * `LIFECYCLE_STATE_UNSPECIFIED` - Unspecified state. This is only
192
+ # used/useful for distinguishing unset values.
204
193
  #
205
194
  def state
206
- @gapi["lifecycleState"]
195
+ @gapi.lifecycle_state
207
196
  end
208
197
 
209
198
  ##
@@ -255,12 +244,10 @@ module Gcloud
255
244
  def update
256
245
  updater = Updater.from_project self
257
246
  yield updater
258
- resp = connection.update_project updater.gapi
259
- if resp.success?
260
- @gapi = resp.data
261
- else
262
- fail ApiError.from_response(resp)
247
+ if updater.gapi.to_h != @gapi.to_h # changed
248
+ @gapi = service.update_project updater.gapi
263
249
  end
250
+ self
264
251
  end
265
252
 
266
253
  ##
@@ -276,12 +263,7 @@ module Gcloud
276
263
  # project.reload!
277
264
  #
278
265
  def reload!
279
- resp = connection.get_project project_id
280
- if resp.success?
281
- @gapi = resp.data
282
- else
283
- fail ApiError.from_response(resp)
284
- end
266
+ @gapi = service.get_project project_id
285
267
  end
286
268
  alias_method :refresh!, :reload!
287
269
 
@@ -317,13 +299,9 @@ module Gcloud
317
299
  # project.delete_requested? #=> true
318
300
  #
319
301
  def delete
320
- resp = connection.delete_project project_id
321
- if resp.success?
322
- reload!
323
- true
324
- else
325
- fail ApiError.from_response(resp)
326
- end
302
+ service.delete_project project_id
303
+ reload!
304
+ true
327
305
  end
328
306
 
329
307
  ##
@@ -346,85 +324,92 @@ module Gcloud
346
324
  # project.active? #=> true
347
325
  #
348
326
  def undelete
349
- resp = connection.undelete_project project_id
350
- if resp.success?
351
- reload!
352
- true
353
- else
354
- fail ApiError.from_response(resp)
355
- end
327
+ service.undelete_project project_id
328
+ reload!
329
+ true
356
330
  end
357
331
 
358
332
  ##
359
- # Gets the [Cloud IAM](https://cloud.google.com/iam/) access control
360
- # policy. Returns a hash that conforms to the following structure:
361
- #
362
- # {
363
- # "bindings" => [{
364
- # "role" => "roles/viewer",
365
- # "members" => ["serviceAccount:your-service-account"]
366
- # }],
367
- # "version" => 0,
368
- # "etag" => "CAE="
369
- # }
333
+ # Gets and updates the [Cloud IAM](https://cloud.google.com/iam/) access
334
+ # control policy for this project.
370
335
  #
371
336
  # @see https://cloud.google.com/iam/docs/managing-policies Managing
372
337
  # Policies
338
+ # @see https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/setIamPolicy
339
+ # projects.setIamPolicy
373
340
  #
374
341
  # @param [Boolean] force Force load the latest policy when `true`.
375
342
  # Otherwise the policy will be memoized to reduce the number of API
376
343
  # calls made. The default is `false`.
377
344
  #
378
- # @return [Hash] See description
345
+ # @yield [policy] A block for updating the policy. The latest policy will
346
+ # be read from the service and passed to the block. After the block
347
+ # completes, the modified policy will be written to the service.
348
+ # @yieldparam [Policy] policy the current Cloud IAM Policy for this
349
+ # project
350
+ #
351
+ # @return [Policy] the current Cloud IAM Policy for this project
379
352
  #
380
- # @example Policy values are memoized by default:
353
+ # @example Policy values are memoized to reduce the number of API calls:
381
354
  # require "gcloud"
382
355
  #
383
356
  # gcloud = Gcloud.new
384
357
  # resource_manager = gcloud.resource_manager
385
358
  # project = resource_manager.project "tokyo-rain-123"
386
- # policy = project.policy
387
359
  #
388
- # puts policy["bindings"]
389
- # puts policy["version"]
390
- # puts policy["etag"]
360
+ # policy = project.policy # API call
361
+ # policy_2 = project.policy # No API call
391
362
  #
392
- # @example Use the `force` option to retrieve the latest policy:
363
+ # @example Use `force` to retrieve the latest policy from the service:
393
364
  # require "gcloud"
394
365
  #
395
366
  # gcloud = Gcloud.new
396
367
  # resource_manager = gcloud.resource_manager
397
368
  # project = resource_manager.project "tokyo-rain-123"
398
- # policy = project.policy force: true
369
+ #
370
+ # policy = project.policy force: true # API call
371
+ # policy_2 = project.policy force: true # API call
372
+ #
373
+ # @example Update the policy by passing a block:
374
+ # require "gcloud"
375
+ #
376
+ # gcloud = Gcloud.new
377
+ # resource_manager = gcloud.resource_manager
378
+ # project = resource_manager.project "tokyo-rain-123"
379
+ #
380
+ # policy = project.policy do |p|
381
+ # p.add "roles/owner", "user:owner@example.com"
382
+ # end # 2 API calls
399
383
  #
400
384
  def policy force: false
401
- @policy = nil if force
385
+ @policy = nil if force || block_given?
402
386
  @policy ||= begin
403
- ensure_connection!
404
- resp = connection.get_policy project_id
405
- fail ApiError.from_response(resp) unless resp.success?
406
- policy = resp.data
407
- policy = policy.to_hash if policy.respond_to? :to_hash
408
- policy
387
+ ensure_service!
388
+ gapi = service.get_policy project_id
389
+ Policy.from_gapi gapi
409
390
  end
391
+ return @policy unless block_given?
392
+ p = @policy.deep_dup
393
+ yield p
394
+ self.policy = p
410
395
  end
411
396
 
412
397
  ##
413
- # Sets the [Cloud IAM](https://cloud.google.com/iam/) access control
414
- # policy.
398
+ # Updates the [Cloud IAM](https://cloud.google.com/iam/) access control
399
+ # policy for this project. The policy should be read from {#policy}.
400
+ # See {Gcloud::ResourceManager::Policy} for an explanation of the policy
401
+ # `etag` property and how to modify policies.
402
+ #
403
+ # You can also update the policy by passing a block to {#policy}, which
404
+ # will call this method internally after the block completes.
415
405
  #
416
406
  # @see https://cloud.google.com/iam/docs/managing-policies Managing
417
407
  # Policies
408
+ # @see https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/setIamPolicy
409
+ # projects.setIamPolicy
418
410
  #
419
- # @param [String] new_policy A hash that conforms to the following
420
- # structure:
421
- #
422
- # {
423
- # "bindings" => [{
424
- # "role" => "roles/viewer",
425
- # "members" => ["serviceAccount:your-service-account"]
426
- # }]
427
- # }
411
+ # @param [Policy] new_policy a new or modified Cloud IAM Policy for this
412
+ # project
428
413
  #
429
414
  # @example
430
415
  # require "gcloud"
@@ -433,23 +418,18 @@ module Gcloud
433
418
  # resource_manager = gcloud.resource_manager
434
419
  # project = resource_manager.project "tokyo-rain-123"
435
420
  #
436
- # viewer_policy = {
437
- # "bindings" => [{
438
- # "role" => "roles/viewer",
439
- # "members" => ["serviceAccount:your-service-account"]
440
- # }]
441
- # }
442
- # project.policy = viewer_policy
421
+ # policy = project.policy # API call
422
+ #
423
+ # policy.add "roles/owner", "user:owner@example.com"
424
+ #
425
+ # project.policy = policy # API call
443
426
  #
444
427
  def policy= new_policy
445
- ensure_connection!
446
- resp = connection.set_policy project_id, new_policy
447
- if resp.success?
448
- @policy = resp.data
449
- @policy = @policy.to_hash if @policy.respond_to? :to_hash
450
- else
451
- fail ApiError.from_response(resp)
452
- end
428
+ ensure_service!
429
+ gapi = service.set_policy project_id, new_policy.to_gapi
430
+ # Convert symbols to strings for backwards compatibility.
431
+ # This will go away when we add a ResourceManager::Policy class.
432
+ @policy = Policy.from_gapi gapi
453
433
  end
454
434
 
455
435
  ##
@@ -478,30 +458,26 @@ module Gcloud
478
458
  #
479
459
  def test_permissions *permissions
480
460
  permissions = Array(permissions).flatten
481
- ensure_connection!
482
- resp = connection.test_permissions project_id, permissions
483
- if resp.success?
484
- Array(resp.data["permissions"])
485
- else
486
- fail ApiError.from_response(resp)
487
- end
461
+ ensure_service!
462
+ gapi = service.test_permissions project_id, permissions
463
+ gapi.permissions
488
464
  end
489
465
 
490
466
  ##
491
467
  # @private New Change from a Google API Client object.
492
- def self.from_gapi gapi, connection
468
+ def self.from_gapi gapi, service
493
469
  new.tap do |p|
494
470
  p.gapi = gapi
495
- p.connection = connection
471
+ p.service = service
496
472
  end
497
473
  end
498
474
 
499
475
  protected
500
476
 
501
477
  ##
502
- # Raise an error unless an active connection is available.
503
- def ensure_connection!
504
- fail "Must have active connection" unless connection
478
+ # Raise an error unless an active service is available.
479
+ def ensure_service!
480
+ fail "Must have active connection" unless service
505
481
  end
506
482
  end
507
483
  end