google-cloud-bigquery 1.22.0 → 1.27.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -37,8 +37,8 @@ module Google
37
37
  # bigquery = Google::Cloud::Bigquery.new
38
38
  # dataset = bigquery.dataset "my_dataset"
39
39
  #
40
- # gs_url = "gs://my-bucket/file-name.csv"
41
- # load_job = dataset.load_job "my_new_table", gs_url do |schema|
40
+ # gcs_uri = "gs://my-bucket/file-name.csv"
41
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |schema|
42
42
  # schema.string "first_name", mode: :required
43
43
  # schema.record "cities_lived", mode: :repeated do |nested_schema|
44
44
  # nested_schema.string "place", mode: :required
@@ -112,8 +112,7 @@ module Google
112
112
  # `false` otherwise.
113
113
  #
114
114
  def iso8859_1?
115
- val = @gapi.configuration.load.encoding
116
- val == "ISO-8859-1"
115
+ @gapi.configuration.load.encoding == "ISO-8859-1"
117
116
  end
118
117
 
119
118
  ##
@@ -195,8 +194,7 @@ module Google
195
194
  # `NEWLINE_DELIMITED_JSON`, `false` otherwise.
196
195
  #
197
196
  def json?
198
- val = @gapi.configuration.load.source_format
199
- val == "NEWLINE_DELIMITED_JSON"
197
+ @gapi.configuration.load.source_format == "NEWLINE_DELIMITED_JSON"
200
198
  end
201
199
 
202
200
  ##
@@ -218,8 +216,27 @@ module Google
218
216
  # `false` otherwise.
219
217
  #
220
218
  def backup?
221
- val = @gapi.configuration.load.source_format
222
- val == "DATASTORE_BACKUP"
219
+ @gapi.configuration.load.source_format == "DATASTORE_BACKUP"
220
+ end
221
+
222
+ ##
223
+ # Checks if the source format is ORC.
224
+ #
225
+ # @return [Boolean] `true` when the source format is `ORC`,
226
+ # `false` otherwise.
227
+ #
228
+ def orc?
229
+ @gapi.configuration.load.source_format == "ORC"
230
+ end
231
+
232
+ ##
233
+ # Checks if the source format is Parquet.
234
+ #
235
+ # @return [Boolean] `true` when the source format is `PARQUET`,
236
+ # `false` otherwise.
237
+ #
238
+ def parquet?
239
+ @gapi.configuration.load.source_format == "PARQUET"
223
240
  end
224
241
 
225
242
  ##
@@ -347,6 +364,58 @@ module Google
347
364
  nil
348
365
  end
349
366
 
367
+ ###
368
+ # Checks if hive partitioning options are set.
369
+ #
370
+ # @see https://cloud.google.com/bigquery/docs/hive-partitioned-loads-gcs Loading externally partitioned data
371
+ #
372
+ # @return [Boolean] `true` when hive partitioning options are set, or `false` otherwise.
373
+ #
374
+ # @!group Attributes
375
+ #
376
+ def hive_partitioning?
377
+ !@gapi.configuration.load.hive_partitioning_options.nil?
378
+ end
379
+
380
+ ###
381
+ # The mode of hive partitioning to use when reading data. The following modes are supported:
382
+ #
383
+ # 1. `AUTO`: automatically infer partition key name(s) and type(s).
384
+ # 2. `STRINGS`: automatically infer partition key name(s). All types are interpreted as strings.
385
+ # 3. `CUSTOM`: partition key schema is encoded in the source URI prefix.
386
+ #
387
+ # @see https://cloud.google.com/bigquery/docs/hive-partitioned-loads-gcs Loading externally partitioned data
388
+ #
389
+ # @return [String, nil] The mode of hive partitioning, or `nil` if not set.
390
+ #
391
+ # @!group Attributes
392
+ #
393
+ def hive_partitioning_mode
394
+ @gapi.configuration.load.hive_partitioning_options.mode if hive_partitioning?
395
+ end
396
+
397
+ ###
398
+ # The common prefix for all source uris when hive partition detection is requested. The prefix must end
399
+ # immediately before the partition key encoding begins. For example, consider files following this data layout:
400
+ #
401
+ # ```
402
+ # gs://bucket/path_to_table/dt=2019-01-01/country=BR/id=7/file.avro
403
+ # gs://bucket/path_to_table/dt=2018-12-31/country=CA/id=3/file.avro
404
+ # ```
405
+ #
406
+ # When hive partitioning is requested with either `AUTO` or `STRINGS` mode, the common prefix can be either of
407
+ # `gs://bucket/path_to_table` or `gs://bucket/path_to_table/` (trailing slash does not matter).
408
+ #
409
+ # @see https://cloud.google.com/bigquery/docs/hive-partitioned-loads-gcs Loading externally partitioned data
410
+ #
411
+ # @return [String, nil] The common prefix for all source uris, or `nil` if not set.
412
+ #
413
+ # @!group Attributes
414
+ #
415
+ def hive_partitioning_source_uri_prefix
416
+ @gapi.configuration.load.hive_partitioning_options.source_uri_prefix if hive_partitioning?
417
+ end
418
+
350
419
  ###
351
420
  # Checks if the destination table will be range partitioned. See [Creating and using integer range partitioned
352
421
  # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
@@ -428,8 +497,9 @@ module Google
428
497
  # The period for which the destination table will be time partitioned, if
429
498
  # any. See [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
430
499
  #
431
- # @return [String, nil] The time partition type. Currently the only supported
432
- # value is "DAY", or `nil` if not present.
500
+ # @return [String, nil] The time partition type. The supported types are `DAY`,
501
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
502
+ # hour, month, and year, respectively; or `nil` if not present.
433
503
  #
434
504
  # @!group Attributes
435
505
  #
@@ -1325,6 +1395,89 @@ module Google
1325
1395
  @gapi.configuration.update! labels: val
1326
1396
  end
1327
1397
 
1398
+ ##
1399
+ # Sets the mode of hive partitioning to use when reading data. The following modes are supported:
1400
+ #
1401
+ # 1. `auto`: automatically infer partition key name(s) and type(s).
1402
+ # 2. `strings`: automatically infer partition key name(s). All types are interpreted as strings.
1403
+ # 3. `custom`: partition key schema is encoded in the source URI prefix.
1404
+ #
1405
+ # Not all storage formats support hive partitioning. Requesting hive partitioning on an unsupported format
1406
+ # will lead to an error. Currently supported types include: `avro`, `csv`, `json`, `orc` and `parquet`.
1407
+ #
1408
+ # See {#format=} and {#hive_partitioning_source_uri_prefix=}.
1409
+ #
1410
+ # @see https://cloud.google.com/bigquery/docs/hive-partitioned-loads-gcs Loading externally partitioned data
1411
+ #
1412
+ # @param [String, Symbol] mode The mode of hive partitioning to use when reading data.
1413
+ #
1414
+ # @example
1415
+ # require "google/cloud/bigquery"
1416
+ #
1417
+ # bigquery = Google::Cloud::Bigquery.new
1418
+ # dataset = bigquery.dataset "my_dataset"
1419
+ #
1420
+ # gcs_uri = "gs://cloud-samples-data/bigquery/hive-partitioning-samples/autolayout/*"
1421
+ # source_uri_prefix = "gs://cloud-samples-data/bigquery/hive-partitioning-samples/autolayout/"
1422
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1423
+ # job.format = :parquet
1424
+ # job.hive_partitioning_mode = :auto
1425
+ # job.hive_partitioning_source_uri_prefix = source_uri_prefix
1426
+ # end
1427
+ #
1428
+ # load_job.wait_until_done!
1429
+ # load_job.done? #=> true
1430
+ #
1431
+ # @!group Attributes
1432
+ #
1433
+ def hive_partitioning_mode= mode
1434
+ @gapi.configuration.load.hive_partitioning_options ||= Google::Apis::BigqueryV2::HivePartitioningOptions.new
1435
+ @gapi.configuration.load.hive_partitioning_options.mode = mode.to_s.upcase
1436
+ end
1437
+
1438
+ ##
1439
+ # Sets the common prefix for all source uris when hive partition detection is requested. The prefix must end
1440
+ # immediately before the partition key encoding begins. For example, consider files following this data
1441
+ # layout:
1442
+ #
1443
+ # ```
1444
+ # gs://bucket/path_to_table/dt=2019-01-01/country=BR/id=7/file.avro
1445
+ # gs://bucket/path_to_table/dt=2018-12-31/country=CA/id=3/file.avro
1446
+ # ```
1447
+ #
1448
+ # When hive partitioning is requested with either `AUTO` or `STRINGS` mode, the common prefix can be either of
1449
+ # `gs://bucket/path_to_table` or `gs://bucket/path_to_table/` (trailing slash does not matter).
1450
+ #
1451
+ # See {#hive_partitioning_mode=}.
1452
+ #
1453
+ # @see https://cloud.google.com/bigquery/docs/hive-partitioned-loads-gcs Loading externally partitioned data
1454
+ #
1455
+ # @param [String] source_uri_prefix The common prefix for all source uris.
1456
+ #
1457
+ # @example
1458
+ # require "google/cloud/bigquery"
1459
+ #
1460
+ # bigquery = Google::Cloud::Bigquery.new
1461
+ # dataset = bigquery.dataset "my_dataset"
1462
+ #
1463
+ # gcs_uri = "gs://cloud-samples-data/bigquery/hive-partitioning-samples/autolayout/*"
1464
+ # source_uri_prefix = "gs://cloud-samples-data/bigquery/hive-partitioning-samples/autolayout/"
1465
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1466
+ # job.format = :parquet
1467
+ # job.hive_partitioning_mode = :auto
1468
+ # job.hive_partitioning_source_uri_prefix = source_uri_prefix
1469
+ # end
1470
+ #
1471
+ # load_job.wait_until_done!
1472
+ # load_job.done? #=> true
1473
+ #
1474
+ # @!group Attributes
1475
+ #
1476
+ def hive_partitioning_source_uri_prefix= source_uri_prefix
1477
+ @gapi.configuration.load.hive_partitioning_options ||= Google::Apis::BigqueryV2::HivePartitioningOptions.new
1478
+ @gapi.configuration.load.hive_partitioning_options.source_uri_prefix = source_uri_prefix
1479
+ end
1480
+
1328
1481
  ##
1329
1482
  # Sets the field on which to range partition the table. See [Creating and using integer range partitioned
1330
1483
  # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
@@ -1344,8 +1497,8 @@ module Google
1344
1497
  # bigquery = Google::Cloud::Bigquery.new
1345
1498
  # dataset = bigquery.dataset "my_dataset"
1346
1499
  #
1347
- # gs_url = "gs://my-bucket/file-name.csv"
1348
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1500
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1501
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1349
1502
  # job.schema do |schema|
1350
1503
  # schema.integer "my_table_id", mode: :required
1351
1504
  # schema.string "my_table_data", mode: :required
@@ -1385,8 +1538,8 @@ module Google
1385
1538
  # bigquery = Google::Cloud::Bigquery.new
1386
1539
  # dataset = bigquery.dataset "my_dataset"
1387
1540
  #
1388
- # gs_url = "gs://my-bucket/file-name.csv"
1389
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1541
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1542
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1390
1543
  # job.schema do |schema|
1391
1544
  # schema.integer "my_table_id", mode: :required
1392
1545
  # schema.string "my_table_data", mode: :required
@@ -1426,8 +1579,8 @@ module Google
1426
1579
  # bigquery = Google::Cloud::Bigquery.new
1427
1580
  # dataset = bigquery.dataset "my_dataset"
1428
1581
  #
1429
- # gs_url = "gs://my-bucket/file-name.csv"
1430
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1582
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1583
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1431
1584
  # job.schema do |schema|
1432
1585
  # schema.integer "my_table_id", mode: :required
1433
1586
  # schema.string "my_table_data", mode: :required
@@ -1467,8 +1620,8 @@ module Google
1467
1620
  # bigquery = Google::Cloud::Bigquery.new
1468
1621
  # dataset = bigquery.dataset "my_dataset"
1469
1622
  #
1470
- # gs_url = "gs://my-bucket/file-name.csv"
1471
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1623
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1624
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1472
1625
  # job.schema do |schema|
1473
1626
  # schema.integer "my_table_id", mode: :required
1474
1627
  # schema.string "my_table_data", mode: :required
@@ -1499,8 +1652,9 @@ module Google
1499
1652
  # BigQuery does not allow you to change partitioning on an existing
1500
1653
  # table.
1501
1654
  #
1502
- # @param [String] type The time partition type. Currently the only
1503
- # supported value is "DAY".
1655
+ # @param [String] type The time partition type. The supported types are `DAY`,
1656
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
1657
+ # hour, month, and year, respectively.
1504
1658
  #
1505
1659
  # @example
1506
1660
  # require "google/cloud/bigquery"
@@ -1508,8 +1662,8 @@ module Google
1508
1662
  # bigquery = Google::Cloud::Bigquery.new
1509
1663
  # dataset = bigquery.dataset "my_dataset"
1510
1664
  #
1511
- # gs_url = "gs://my-bucket/file-name.csv"
1512
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1665
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1666
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1513
1667
  # job.time_partitioning_type = "DAY"
1514
1668
  # end
1515
1669
  #
@@ -1547,8 +1701,8 @@ module Google
1547
1701
  # bigquery = Google::Cloud::Bigquery.new
1548
1702
  # dataset = bigquery.dataset "my_dataset"
1549
1703
  #
1550
- # gs_url = "gs://my-bucket/file-name.csv"
1551
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1704
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1705
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1552
1706
  # job.time_partitioning_type = "DAY"
1553
1707
  # job.time_partitioning_field = "dob"
1554
1708
  # job.schema do |schema|
@@ -1583,8 +1737,8 @@ module Google
1583
1737
  # bigquery = Google::Cloud::Bigquery.new
1584
1738
  # dataset = bigquery.dataset "my_dataset"
1585
1739
  #
1586
- # gs_url = "gs://my-bucket/file-name.csv"
1587
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1740
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1741
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1588
1742
  # job.time_partitioning_type = "DAY"
1589
1743
  # job.time_partitioning_expiration = 86_400
1590
1744
  # end
@@ -1643,8 +1797,8 @@ module Google
1643
1797
  # bigquery = Google::Cloud::Bigquery.new
1644
1798
  # dataset = bigquery.dataset "my_dataset"
1645
1799
  #
1646
- # gs_url = "gs://my-bucket/file-name.csv"
1647
- # load_job = dataset.load_job "my_new_table", gs_url do |job|
1800
+ # gcs_uri = "gs://my-bucket/file-name.csv"
1801
+ # load_job = dataset.load_job "my_new_table", gcs_uri do |job|
1648
1802
  # job.time_partitioning_type = "DAY"
1649
1803
  # job.time_partitioning_field = "dob"
1650
1804
  # job.schema do |schema|
@@ -0,0 +1,431 @@
1
+ # Copyright 2020 Google LLC
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
+ # https://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 "google/apis/bigquery_v2"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Bigquery
21
+ ##
22
+ # # Policy
23
+ #
24
+ # Represents a Cloud IAM Policy for BigQuery resources.
25
+ #
26
+ # A Policy is a collection of bindings. A {Policy::Binding} binds one or more members to a single role. Member
27
+ # strings can describe user accounts, service accounts, Google groups, and domains. A role string represents a
28
+ # named list of permissions; each role can be an IAM predefined role or a user-created custom role.
29
+ #
30
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
31
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
32
+ #
33
+ # @attr [String] etag Used to check if the policy has changed since the last request. When you make a request with
34
+ # an `etag` value, Cloud IAM compares the `etag` value in the request with the existing `etag` value associated
35
+ # with the policy. It writes the policy only if the `etag` values match.
36
+ # @attr [Array<Binding>] bindings The bindings in the policy, which may be mutable or frozen depending on the
37
+ # context. See [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of
38
+ # primitive and curated roles. See [BigQuery Table ACL
39
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
40
+ # values and patterns for members.
41
+ #
42
+ # @example
43
+ # require "google/cloud/bigquery"
44
+ #
45
+ # bigquery = Google::Cloud::Bigquery.new
46
+ # dataset = bigquery.dataset "my_dataset"
47
+ # table = dataset.table "my_table"
48
+ # policy = table.policy
49
+ #
50
+ # policy.frozen? #=> true
51
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
52
+ #
53
+ # binding_owner.role #=> "roles/owner"
54
+ # binding_owner.members #=> ["user:owner@example.com"]
55
+ # binding_owner.frozen? #=> true
56
+ # binding_owner.members.frozen? #=> true
57
+ #
58
+ # @example Update mutable bindings in the policy.
59
+ # require "google/cloud/bigquery"
60
+ #
61
+ # bigquery = Google::Cloud::Bigquery.new
62
+ # dataset = bigquery.dataset "my_dataset"
63
+ # table = dataset.table "my_table"
64
+ #
65
+ # table.update_policy do |p|
66
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
67
+ # p.revoke role: "roles/editor", members: "user:editor@example.com"
68
+ # p.revoke role: "roles/owner"
69
+ # end
70
+ #
71
+ # @example Iterate over frozen bindings.
72
+ # require "google/cloud/bigquery"
73
+ #
74
+ # bigquery = Google::Cloud::Bigquery.new
75
+ # dataset = bigquery.dataset "my_dataset"
76
+ # table = dataset.table "my_table"
77
+ # policy = table.policy
78
+ #
79
+ # policy.frozen? #=> true
80
+ # policy.bindings.each do |b|
81
+ # puts b.role
82
+ # puts b.members
83
+ # end
84
+ #
85
+ # @example Update mutable bindings.
86
+ # require "google/cloud/bigquery"
87
+ #
88
+ # bigquery = Google::Cloud::Bigquery.new
89
+ # dataset = bigquery.dataset "my_dataset"
90
+ # table = dataset.table "my_table"
91
+ #
92
+ # table.update_policy do |p|
93
+ # p.bindings.each do |b|
94
+ # b.members.delete_if { |m| m.include? "@example.com" }
95
+ # end
96
+ # end
97
+ #
98
+ class Policy
99
+ attr_reader :etag, :bindings
100
+
101
+ # @private
102
+ def initialize etag, bindings
103
+ @etag = etag.freeze
104
+ @bindings = bindings
105
+ end
106
+
107
+ ##
108
+ # Convenience method adding or updating a binding in the policy. See [Understanding
109
+ # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and curated roles. See
110
+ # [BigQuery Table ACL
111
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
112
+ # values and patterns for members.
113
+ #
114
+ # @param [String] role The role that is bound to members in the binding. For example, `roles/viewer`,
115
+ # `roles/editor`, or `roles/owner`. Required.
116
+ # @param [String, Array<String>] members Specifies the identities requesting access for a Cloud Platform
117
+ # resource. `members` can have the following values. Required.
118
+ #
119
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
120
+ # account.
121
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
122
+ # account or a service account.
123
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
124
+ # `alice@example.com`.
125
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
126
+ # `my-other-app@appspot.gserviceaccount.com`.
127
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
128
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
129
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
130
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
131
+ # binding.
132
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
133
+ # a service account that has been recently deleted. For example,
134
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
135
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
136
+ # the binding.
137
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
138
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
139
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
140
+ # the binding.
141
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
142
+ # `google.com` or `example.com`.
143
+ #
144
+ # @return [nil]
145
+ #
146
+ # @example Grant a role to a member.
147
+ # require "google/cloud/bigquery"
148
+ #
149
+ # bigquery = Google::Cloud::Bigquery.new
150
+ # dataset = bigquery.dataset "my_dataset"
151
+ # table = dataset.table "my_table"
152
+ #
153
+ # table.update_policy do |p|
154
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
155
+ # end
156
+ #
157
+ def grant role:, members:
158
+ existing_binding = bindings.find { |b| b.role == role }
159
+ if existing_binding
160
+ existing_binding.members.concat Array(members)
161
+ existing_binding.members.uniq!
162
+ else
163
+ bindings << Binding.new(role, members)
164
+ end
165
+ nil
166
+ end
167
+
168
+ ##
169
+ # Convenience method for removing a binding or bindings from the policy. See
170
+ # [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a list of primitive and
171
+ # curated roles. See [BigQuery Table ACL
172
+ # permissions](https://cloud.google.com/bigquery/docs/table-access-controls-intro#permissions) for a list of
173
+ # values and patterns for members.
174
+ #
175
+ # @param [String] role A role that is bound to members in the policy. For example, `roles/viewer`,
176
+ # `roles/editor`, or `roles/owner`. Optional.
177
+ # @param [String, Array<String>] members Specifies the identities receiving access for a Cloud Platform
178
+ # resource. `members` can have the following values. Optional.
179
+ #
180
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
181
+ # account.
182
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
183
+ # account or a service account.
184
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
185
+ # `alice@example.com`.
186
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
187
+ # `my-other-app@appspot.gserviceaccount.com`.
188
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
189
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
190
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
191
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
192
+ # binding.
193
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
194
+ # a service account that has been recently deleted. For example,
195
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
196
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
197
+ # the binding.
198
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
199
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
200
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
201
+ # the binding.
202
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
203
+ # `google.com` or `example.com`.
204
+ #
205
+ # @return [nil]
206
+ #
207
+ # @example Revoke a role for a member or members.
208
+ # require "google/cloud/bigquery"
209
+ #
210
+ # bigquery = Google::Cloud::Bigquery.new
211
+ # dataset = bigquery.dataset "my_dataset"
212
+ # table = dataset.table "my_table"
213
+ #
214
+ # table.update_policy do |p|
215
+ # p.revoke role: "roles/viewer", members: "user:viewer@example.com"
216
+ # end
217
+ #
218
+ # @example Revoke a role for all members.
219
+ # require "google/cloud/bigquery"
220
+ #
221
+ # bigquery = Google::Cloud::Bigquery.new
222
+ # dataset = bigquery.dataset "my_dataset"
223
+ # table = dataset.table "my_table"
224
+ #
225
+ # table.update_policy do |p|
226
+ # p.revoke role: "roles/viewer"
227
+ # end
228
+ #
229
+ # @example Revoke all roles for a member or members.
230
+ # require "google/cloud/bigquery"
231
+ #
232
+ # bigquery = Google::Cloud::Bigquery.new
233
+ # dataset = bigquery.dataset "my_dataset"
234
+ # table = dataset.table "my_table"
235
+ #
236
+ # table.update_policy do |p|
237
+ # p.revoke members: ["user:viewer@example.com", "user:editor@example.com"]
238
+ # end
239
+ #
240
+ def revoke role: nil, members: nil
241
+ bindings_for_role = role ? bindings.select { |b| b.role == role } : bindings
242
+ bindings_for_role.each do |b|
243
+ if members
244
+ b.members -= Array(members)
245
+ bindings.delete b if b.members.empty?
246
+ else
247
+ bindings.delete b
248
+ end
249
+ end
250
+ nil
251
+ end
252
+
253
+ ##
254
+ # @private Convert the Policy to a Google::Apis::BigqueryV2::Policy.
255
+ def to_gapi
256
+ Google::Apis::BigqueryV2::Policy.new(
257
+ bindings: bindings_to_gapi,
258
+ etag: etag,
259
+ version: 1
260
+ )
261
+ end
262
+
263
+ ##
264
+ # @private Deep freeze the policy including its bindings.
265
+ def freeze
266
+ super
267
+ @bindings.each(&:freeze)
268
+ @bindings.freeze
269
+ self
270
+ end
271
+
272
+ ##
273
+ # @private New Policy from a Google::Apis::BigqueryV2::Policy object.
274
+ def self.from_gapi gapi
275
+ bindings = Array(gapi.bindings).map do |binding|
276
+ Binding.new binding.role, binding.members.to_a
277
+ end
278
+ new gapi.etag, bindings
279
+ end
280
+
281
+ ##
282
+ # # Policy::Binding
283
+ #
284
+ # Represents a Cloud IAM Binding for BigQuery resources within the context of a {Policy}.
285
+ #
286
+ # A binding binds one or more members to a single role. Member strings can describe user accounts, service
287
+ # accounts, Google groups, and domains. A role is a named list of permissions; each role can be an IAM
288
+ # predefined role or a user-created custom role.
289
+ #
290
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
291
+ #
292
+ # @attr [String] role The role that is assigned to `members`. For example, `roles/viewer`, `roles/editor`, or
293
+ # `roles/owner`. Required.
294
+ # @attr [Array<String>] members Specifies the identities requesting access for a Cloud Platform resource.
295
+ # `members` can have the following values. Required.
296
+ #
297
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
298
+ # account.
299
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
300
+ # account or a service account.
301
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
302
+ # `alice@example.com`.
303
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
304
+ # `my-other-app@appspot.gserviceaccount.com`.
305
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
306
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
307
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
308
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
309
+ # binding.
310
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing
311
+ # a service account that has been recently deleted. For example,
312
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is undeleted,
313
+ # this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains the role in
314
+ # the binding.
315
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a Google
316
+ # group that has been recently deleted. For example, `admins@example.com?uid=123456789012345678901`. If the
317
+ # group is recovered, this value reverts to `group:<emailid>` and the recovered group retains the role in
318
+ # the binding.
319
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For example,
320
+ # `google.com` or `example.com`.
321
+ #
322
+ # @example
323
+ # require "google/cloud/bigquery"
324
+ #
325
+ # bigquery = Google::Cloud::Bigquery.new
326
+ # dataset = bigquery.dataset "my_dataset"
327
+ # table = dataset.table "my_table"
328
+ #
329
+ # policy = table.policy
330
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
331
+ #
332
+ # binding_owner.role #=> "roles/owner"
333
+ # binding_owner.members #=> ["user:owner@example.com"]
334
+ #
335
+ # binding_owner.frozen? #=> true
336
+ # binding_owner.members.frozen? #=> true
337
+ #
338
+ # @example Update mutable bindings.
339
+ # require "google/cloud/bigquery"
340
+ #
341
+ # bigquery = Google::Cloud::Bigquery.new
342
+ # dataset = bigquery.dataset "my_dataset"
343
+ # table = dataset.table "my_table"
344
+ #
345
+ # table.update_policy do |p|
346
+ # binding_owner = p.bindings.find { |b| b.role == "roles/owner" }
347
+ # binding_owner.members.delete_if { |m| m.include? "@example.com" }
348
+ # end
349
+ #
350
+ class Binding
351
+ attr_accessor :role
352
+ attr_reader :members
353
+
354
+ # @private
355
+ def initialize role, members
356
+ members = Array(members).uniq
357
+ raise ArgumentError, "members cannot be empty" if members.empty?
358
+ @role = role
359
+ @members = members
360
+ end
361
+
362
+ ##
363
+ # Sets the binding members.
364
+ #
365
+ # @param [Array<String>] new_members Specifies the identities requesting access for a Cloud Platform resource.
366
+ # `new_members` can have the following values. Required.
367
+ #
368
+ # * `allUsers`: A special identifier that represents anyone who is on the internet; with or without a Google
369
+ # account.
370
+ # * `allAuthenticatedUsers`: A special identifier that represents anyone who is authenticated with a Google
371
+ # account or a service account.
372
+ # * `user:<emailid>`: An email address that represents a specific Google account. For example,
373
+ # `alice@example.com`.
374
+ # * `serviceAccount:<emailid>`: An email address that represents a service account. For example,
375
+ # `my-other-app@appspot.gserviceaccount.com`.
376
+ # * `group:<emailid>`: An email address that represents a Google group. For example, `admins@example.com`.
377
+ # * `deleted:user:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a user
378
+ # that has been recently deleted. For example, `alice@example.com?uid=123456789012345678901`. If the user
379
+ # is recovered, this value reverts to `user:<emailid>` and the recovered user retains the role in the
380
+ # binding.
381
+ # * `deleted: serviceAccount:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier)
382
+ # representing a service account that has been recently deleted. For example,
383
+ # `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the service account is
384
+ # undeleted, this value reverts to `serviceAccount:<emailid>` and the undeleted service account retains
385
+ # the role in the binding.
386
+ # * `deleted:group:<emailid>?uid=<uniqueid>`: An email address (plus unique identifier) representing a
387
+ # Google group that has been recently deleted. For example,
388
+ # `admins@example.com?uid=123456789012345678901`. If the group is recovered, this value reverts to
389
+ # `group:<emailid>` and the recovered group retains the role in the binding.
390
+ # * `domain:<domain>`: The G Suite domain (primary) that represents all the users of that domain. For
391
+ # example, `google.com` or `example.com`.
392
+ #
393
+ def members= new_members
394
+ @members = Array(new_members).uniq
395
+ end
396
+
397
+ ##
398
+ # @private Convert the Binding to a Google::Apis::BigqueryV2::Binding.
399
+ def to_gapi
400
+ Google::Apis::BigqueryV2::Binding.new role: role, members: members
401
+ end
402
+
403
+ ##
404
+ # @private Deep freeze the policy including its members.
405
+ def freeze
406
+ super
407
+ role.freeze
408
+ members.each(&:freeze)
409
+ members.freeze
410
+ self
411
+ end
412
+
413
+ ##
414
+ # @private New Binding from a Google::Apis::BigqueryV2::Binding object.
415
+ def self.from_gapi gapi
416
+ new gapi.etag, gapi.members.to_a
417
+ end
418
+ end
419
+
420
+ protected
421
+
422
+ def bindings_to_gapi
423
+ @bindings.compact.uniq.map do |b|
424
+ next if b.members.empty?
425
+ b.to_gapi
426
+ end
427
+ end
428
+ end
429
+ end
430
+ end
431
+ end