From b01056cac354bf3f5281af64fa52d99de6a26877 Mon Sep 17 00:00:00 2001 From: Francisco Javier Alarcon Esparza Date: Mon, 3 Mar 2025 23:16:41 +0000 Subject: [PATCH 1/5] feat(bigquery): add table/view samples to cloud-client --- bigquery/cloud-client/snippets/pom.xml | 70 +++++++++ .../bigquery/GetTableOrViewAccessPolicy.java | 63 ++++++++ .../bigquery/GrantAccessToTableOrView.java | 66 +++++++++ .../bigquery/RevokeAccessToTableOrView.java | 94 ++++++++++++ .../GetTableOrViewAccessPolicyIT.java | 115 +++++++++++++++ .../bigquery/GrantAccessToTableOrViewIT.java | 123 ++++++++++++++++ .../bigquery/RevokeAccessToTableOrViewIT.java | 136 ++++++++++++++++++ 7 files changed, 667 insertions(+) create mode 100644 bigquery/cloud-client/snippets/pom.xml create mode 100644 bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GetTableOrViewAccessPolicy.java create mode 100644 bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GrantAccessToTableOrView.java create mode 100644 bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java create mode 100644 bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java create mode 100644 bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java create mode 100644 bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java diff --git a/bigquery/cloud-client/snippets/pom.xml b/bigquery/cloud-client/snippets/pom.xml new file mode 100644 index 00000000000..4acbac77b79 --- /dev/null +++ b/bigquery/cloud-client/snippets/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + com.example.bigquery + cloud-client-snippets + jar + Google Cloud BigQuery Cloud Client Snippets + + + + com.google.cloud.samples + shared-configuration + 1.2.0 + + + + 21 + 21 + UTF-8 + + + + + + com.google.cloud + libraries-bom + 26.32.0 + pom + import + + + + + + + com.google.cloud + google-cloud-bigquery + + + junit + junit + 4.13.2 + test + + + com.google.truth + truth + 1.4.4 + test + + + diff --git a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GetTableOrViewAccessPolicy.java b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GetTableOrViewAccessPolicy.java new file mode 100644 index 00000000000..2822e86bc7b --- /dev/null +++ b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GetTableOrViewAccessPolicy.java @@ -0,0 +1,63 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +// [START bigquery_view_table_or_view_access_policy] + +import com.google.cloud.Policy; +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryException; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.TableId; + +public class GetTableOrViewAccessPolicy { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + // Project, dataset and resource (table or view) from which to get the access policy. + String projectId = "MY_PROJECT_ID"; + String datasetName = "MY_DATASET_NAME"; + String resourceName = "MY_RESOURCE_NAME"; + getTableOrViewAccessPolicy(projectId, datasetName, resourceName); + } + + public static void getTableOrViewAccessPolicy( + String projectId, String datasetName, String resourceName) { + try { + // Initialize client that will be used to send requests. This client only needs + // to be created once, and can be reused for multiple requests. + BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService(); + + // Create table identity given the projectId, the datasetName and the resourceName. + TableId tableId = TableId.of(projectId, datasetName, resourceName); + + // Get the table IAM policy. + Policy policy = bigquery.getIamPolicy(tableId); + + // Show policy details. + // Find more information about the Policy Class here: + // https://cloud.google.com/java/docs/reference/google-cloud-core/latest/com.google.cloud.Policy + System.out.println( + "IAM policy info of resource \"" + resourceName + "\" retrieved succesfully"); + System.out.println(); + System.out.println("IAM policy info: " + policy.toString()); + } catch (BigQueryException e) { + System.out.println("IAM policy info not retrieved. \n" + e.toString()); + } + } +} + // [END bigquery_view_table_or_view_access_policy] diff --git a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GrantAccessToTableOrView.java b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GrantAccessToTableOrView.java new file mode 100644 index 00000000000..7190652ebec --- /dev/null +++ b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/GrantAccessToTableOrView.java @@ -0,0 +1,66 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +// [START bigquery_grant_access_to_table_or_view] +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.Role; +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryException; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.TableId; + +public class GrantAccessToTableOrView { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + // Project, dataset and resource (table or view) from which to get the access policy. + String projectId = "MY_PROJECT_ID"; + String datasetName = "MY_DATASET_NAME"; + String resourceName = "MY_TABLE_NAME"; + // Role to add to the policy access + Role role = Role.of("roles/bigquery.dataViewer"); + // Identity to add to the policy access + Identity identity = Identity.user("user-add@example.com"); + grantAccessToTableOrView(projectId, datasetName, resourceName, role, identity); + } + + public static void grantAccessToTableOrView( + String projectId, String datasetName, String resourceName, Role role, Identity identity) { + try { + // Initialize client that will be used to send requests. This client only needs + // to be created once, and can be reused for multiple requests. + BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService(); + + // Create table identity given the projectId, the datasetName and the resourceName. + TableId tableId = TableId.of(projectId, datasetName, resourceName); + + // Add new user identity to current IAM policy. + Policy policy = bigquery.getIamPolicy(tableId); + policy = policy.toBuilder().addIdentity(role, identity).build(); + + // Update the IAM policy by setting the new one. + bigquery.setIamPolicy(tableId, policy); + + System.out.println("IAM policy of resource \"" + resourceName + "\" updated successfully"); + } catch (BigQueryException e) { + System.out.println("IAM policy was not updated. \n" + e.toString()); + } + } +} + // [END bigquery_grant_access_to_table_or_view] diff --git a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java new file mode 100644 index 00000000000..f48db2842dd --- /dev/null +++ b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java @@ -0,0 +1,94 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +// [START bigquery_revoke_access_to_table_or_view] +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.Role; +import com.google.cloud.bigquery.BigQuery; +import com.google.cloud.bigquery.BigQueryException; +import com.google.cloud.bigquery.BigQueryOptions; +import com.google.cloud.bigquery.TableId; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class RevokeAccessToTableOrView { + + public static void main(String[] args) { + // TODO(developer): Replace these variables before running the sample. + // Project, dataset and resource (table or view) from which to get the access policy + String projectId = "MY_PROJECT_ID"; + String datasetName = "MY_DATASET_NAME"; + String resourceName = "MY_RESOURCE_NAME"; + // Role to remove from the access policy + Role role = Role.of("roles/bigquery.dataViewer"); + // Identity to remove from the access policy + Identity user = Identity.user("user-add@example.com"); + revokeAccessToTableOrView(projectId, datasetName, resourceName, role, user); + } + + public static void revokeAccessToTableOrView( + String projectId, String datasetName, String resourceName, Role role, Identity identity) { + try { + // Initialize client that will be used to send requests. This client only needs + // to be created once, and can be reused for multiple requests. + BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService(); + + // Create table identity given the projectId, the datasetName and the resourceName. + TableId tableId = TableId.of(projectId, datasetName, resourceName); + + // Remove either identities or roles, or both from bindings and replace it in + // the current IAM policy. + Policy policy = bigquery.getIamPolicy(tableId); + // Create a copy of a inmutable map. + Map> bindings = new HashMap<>(policy.getBindings()); + + // Remove all identities with a specific role. + bindings.remove(role); + // Update bindings. + policy = policy.toBuilder().setBindings(bindings).build(); + + // Remove one identity in all the existing roles. + for (Role roleKey : bindings.keySet()) { + if (bindings.get(roleKey).contains(identity)) { + // Create a copy of a inmutable set if the identity is present in the role. + Set identities = new HashSet<>(bindings.get(roleKey)); + // Remove identity. + identities.remove(identity); + bindings.put(roleKey, identities); + if (bindings.get(roleKey).isEmpty()) { + // Remove the role if it has no identities. + bindings.remove(roleKey); + } + } + } + // Update bindings. + policy = policy.toBuilder().setBindings(bindings).build(); + + // Update the IAM policy by setting the new one. + bigquery.setIamPolicy(tableId, policy); + + System.out.println("IAM policy of resource \"" + resourceName + "\" updated successfully"); + } catch (BigQueryException e) { + System.out.println("IAM policy was not updated. \n" + e.toString()); + } + } +} + // [END bigquery_revoke_access_to_table_or_view] diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java new file mode 100644 index 00000000000..c952a458f72 --- /dev/null +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java @@ -0,0 +1,115 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; +import static junit.framework.TestCase.assertNotNull; + +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class GetTableOrViewAccessPolicyIT { + + private final Logger log = Logger.getLogger(this.getClass().getName()); + private String datasetName; + private String tableName; + private String viewName; + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static final String GOOGLE_CLOUD_PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + + private static String requireEnvVar(String varName) { + String value = System.getenv(varName); + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + return value; + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + + // Create temporary dataset. + datasetName = RemoteBigQueryHelper.generateDatasetName(); + CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Create temporary table. + tableName = "get_access_policy_table_test_" + UUID.randomUUID().toString().substring(0, 8); + Schema schema = + Schema.of( + Field.of("stringField", StandardSQLTypeName.STRING), + Field.of("isBooleanField", StandardSQLTypeName.BOOL)); + CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + + // Create a temporary view. + viewName = "get_access_policy_view_test_" + UUID.randomUUID().toString().substring(0, 8); + String query = + String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); + CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + } + + @After + public void tearDown() { + // Clean up. + DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, viewName); + DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Restores print statements to the original output stream. + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, bout.toString()); + } + + @Test + public void testGetTableOrViewAccessPolicy_getTableAccessPolicy() { + GetTableOrViewAccessPolicy.getTableOrViewAccessPolicy( + GOOGLE_CLOUD_PROJECT, datasetName, tableName); + assertThat(bout.toString()) + .contains("IAM policy info of resource \"" + tableName + "\" retrieved succesfully"); + } + + @Test + public void testGetTableOrViewAccessPolicy_getViewAccessPolicy() { + GetTableOrViewAccessPolicy.getTableOrViewAccessPolicy( + GOOGLE_CLOUD_PROJECT, datasetName, viewName); + assertThat(bout.toString()) + .contains("IAM policy info of resource \"" + viewName + "\" retrieved succesfully"); + } +} diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java new file mode 100644 index 00000000000..12b8c488652 --- /dev/null +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java @@ -0,0 +1,123 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; +import static junit.framework.TestCase.assertNotNull; + +import com.google.cloud.Identity; +import com.google.cloud.Role; +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class GrantAccessToTableOrViewIT { + + private final Logger log = Logger.getLogger(this.getClass().getName()); + private String datasetName; + private String tableName; + private String viewName; + private Role role; + private Identity identity; + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static final String GOOGLE_CLOUD_PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + + private static String requireEnvVar(String varName) { + String value = System.getenv(varName); + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + return value; + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + + // Create temporary dataset. + datasetName = RemoteBigQueryHelper.generateDatasetName(); + CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Create temporary table. + tableName = "grant_access_to_table_test_" + UUID.randomUUID().toString().substring(0, 8); + Schema schema = + Schema.of( + Field.of("stringField", StandardSQLTypeName.STRING), + Field.of("isBooleanField", StandardSQLTypeName.BOOL)); + CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + + // Create a temporary view. + viewName = "grant_access_to_view_test_" + UUID.randomUUID().toString().substring(0, 8); + String query = + String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); + CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + + // Role and identity to add to policy. + role = Role.of("roles/bigquery.dataViewer"); + identity = Identity.group("cloud-developer-relations@google.com"); + } + + @After + public void tearDown() { + // Clean up. + DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, viewName); + DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Restores print statements to the original output stream. + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, bout.toString()); + } + + @Test + public void testGrantAccessToTableOrView_grantAccessToTable() { + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, tableName, role, identity); + assertThat(bout.toString()) + .contains("IAM policy of resource \"" + tableName + "\" updated successfully"); + } + + @Test + public void testGrantAccessToTableOrView_grantAccessToView() { + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, viewName, role, identity); + assertThat(bout.toString()) + .contains("IAM policy of resource \"" + viewName + "\" updated successfully"); + } +} diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java new file mode 100644 index 00000000000..cfa00896c84 --- /dev/null +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java @@ -0,0 +1,136 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.bigquery; + +import static com.google.common.truth.Truth.assertThat; +import static junit.framework.TestCase.assertNotNull; + +import com.google.cloud.Identity; +import com.google.cloud.Role; +import com.google.cloud.bigquery.Field; +import com.google.cloud.bigquery.Schema; +import com.google.cloud.bigquery.StandardSQLTypeName; +import com.google.cloud.bigquery.testing.RemoteBigQueryHelper; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class RevokeAccessToTableOrViewIT { + + private final Logger log = Logger.getLogger(this.getClass().getName()); + private String datasetName; + private String tableName; + private String viewName; + private Role firstRole; + private Role secondRole; + private Identity identity; + private ByteArrayOutputStream bout; + private PrintStream out; + private PrintStream originalPrintStream; + + private static final String GOOGLE_CLOUD_PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + + private static String requireEnvVar(String varName) { + String value = System.getenv(varName); + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + return value; + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + originalPrintStream = System.out; + System.setOut(out); + + // Create temporary dataset. + datasetName = RemoteBigQueryHelper.generateDatasetName(); + CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Create temporary table and view. + tableName = "revoke_access_to_table_test_" + UUID.randomUUID().toString().substring(0, 8); + Schema schema = + Schema.of( + Field.of("stringField", StandardSQLTypeName.STRING), + Field.of("isBooleanField", StandardSQLTypeName.BOOL)); + CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + viewName = "revoke_access_to_view_test_" + UUID.randomUUID().toString().substring(0, 8); + String query = + String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); + CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + + // Role and identity to add to policy. + firstRole = Role.of("roles/bigquery.dataViewer"); + identity = Identity.group("cloud-developer-relations@google.com"); + + // Grant access to table and view. + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, tableName, firstRole, identity); + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, viewName, firstRole, identity); + + // Add a second role for identity. + secondRole = Role.of("roles/bigquery.dataEditor"); + + // Grant access to table and view. + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, tableName, secondRole, identity); + GrantAccessToTableOrView.grantAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, viewName, secondRole, identity); + } + + @After + public void tearDown() { + // Clean up. + DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + + // Restores print statements to the original output stream. + System.out.flush(); + System.setOut(originalPrintStream); + log.log(Level.INFO, bout.toString()); + } + + @Test + public void testRevokeAccessToTableOrView_revokeAccessToTable() { + RevokeAccessToTableOrView.revokeAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, tableName, firstRole, identity); + assertThat(bout.toString()) + .contains("IAM policy of resource \"" + tableName + "\" updated successfully"); + } + + @Test + public void testRevokeAccessToTableOrView_revokeAccessToView() { + RevokeAccessToTableOrView.revokeAccessToTableOrView( + GOOGLE_CLOUD_PROJECT, datasetName, viewName, firstRole, identity); + assertThat(bout.toString()) + .contains("IAM policy of resource \"" + viewName + "\" updated successfully"); + } +} From 6a7b3abb2f9c06dc05af2718b46f5a2fbb077bd3 Mon Sep 17 00:00:00 2001 From: Francisco Javier Alarcon Esparza Date: Tue, 11 Mar 2025 19:29:22 +0000 Subject: [PATCH 2/5] use Util helpers --- .../bigquery/GetTableOrViewAccessPolicyIT.java | 12 ++++++------ .../example/bigquery/GrantAccessToTableOrViewIT.java | 12 ++++++------ .../bigquery/RevokeAccessToTableOrViewIT.java | 11 ++++++----- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java index c952a458f72..30ada040d1a 100644 --- a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GetTableOrViewAccessPolicyIT.java @@ -67,7 +67,7 @@ public void setUp() { // Create temporary dataset. datasetName = RemoteBigQueryHelper.generateDatasetName(); - CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.setUpTest_createDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Create temporary table. tableName = "get_access_policy_table_test_" + UUID.randomUUID().toString().substring(0, 8); @@ -75,21 +75,21 @@ public void setUp() { Schema.of( Field.of("stringField", StandardSQLTypeName.STRING), Field.of("isBooleanField", StandardSQLTypeName.BOOL)); - CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + Util.setUpTest_createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); // Create a temporary view. viewName = "get_access_policy_view_test_" + UUID.randomUUID().toString().substring(0, 8); String query = String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); - CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + Util.setUpTest_createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); } @After public void tearDown() { // Clean up. - DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, viewName); - DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); - DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, viewName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + Util.tearDownTest_deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Restores print statements to the original output stream. System.out.flush(); diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java index 12b8c488652..0909065dd60 100644 --- a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/GrantAccessToTableOrViewIT.java @@ -71,7 +71,7 @@ public void setUp() { // Create temporary dataset. datasetName = RemoteBigQueryHelper.generateDatasetName(); - CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.setUpTest_createDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Create temporary table. tableName = "grant_access_to_table_test_" + UUID.randomUUID().toString().substring(0, 8); @@ -79,13 +79,13 @@ public void setUp() { Schema.of( Field.of("stringField", StandardSQLTypeName.STRING), Field.of("isBooleanField", StandardSQLTypeName.BOOL)); - CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + Util.setUpTest_createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); // Create a temporary view. viewName = "grant_access_to_view_test_" + UUID.randomUUID().toString().substring(0, 8); String query = String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); - CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + Util.setUpTest_createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); // Role and identity to add to policy. role = Role.of("roles/bigquery.dataViewer"); @@ -95,9 +95,9 @@ public void setUp() { @After public void tearDown() { // Clean up. - DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, viewName); - DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); - DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, viewName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + Util.tearDownTest_deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Restores print statements to the original output stream. System.out.flush(); diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java index cfa00896c84..ed1852e2743 100644 --- a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java @@ -72,7 +72,7 @@ public void setUp() { // Create temporary dataset. datasetName = RemoteBigQueryHelper.generateDatasetName(); - CreateDataset.createDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.setUpTest_createDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Create temporary table and view. tableName = "revoke_access_to_table_test_" + UUID.randomUUID().toString().substring(0, 8); @@ -80,11 +80,11 @@ public void setUp() { Schema.of( Field.of("stringField", StandardSQLTypeName.STRING), Field.of("isBooleanField", StandardSQLTypeName.BOOL)); - CreateTable.createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); + Util.setUpTest_createTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName, schema); viewName = "revoke_access_to_view_test_" + UUID.randomUUID().toString().substring(0, 8); String query = String.format("SELECT stringField, isBooleanField FROM %s.%s", datasetName, tableName); - CreateView.createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); + Util.setUpTest_createView(GOOGLE_CLOUD_PROJECT, datasetName, viewName, query); // Role and identity to add to policy. firstRole = Role.of("roles/bigquery.dataViewer"); @@ -109,8 +109,9 @@ public void setUp() { @After public void tearDown() { // Clean up. - DeleteTable.deleteTable(GOOGLE_CLOUD_PROJECT, datasetName, tableName); - DeleteDataset.deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, viewName); + Util.tearDownTest_deleteTableOrView(GOOGLE_CLOUD_PROJECT, datasetName, tableName); + Util.tearDownTest_deleteDataset(GOOGLE_CLOUD_PROJECT, datasetName); // Restores print statements to the original output stream. System.out.flush(); From 527a82b34212905c1517099c87e69f21b10d1c8f Mon Sep 17 00:00:00 2001 From: Francisco Javier Alarcon Esparza Date: Tue, 11 Mar 2025 23:30:48 +0000 Subject: [PATCH 3/5] add helper method grantAccessToTableOrView --- .../bigquery/RevokeAccessToTableOrViewIT.java | 8 ++++---- .../src/test/java/com/example/bigquery/Util.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java index ed1852e2743..5ba3c381073 100644 --- a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/RevokeAccessToTableOrViewIT.java @@ -91,18 +91,18 @@ public void setUp() { identity = Identity.group("cloud-developer-relations@google.com"); // Grant access to table and view. - GrantAccessToTableOrView.grantAccessToTableOrView( + Util.setUpTest_grantAccessToTableOrView( GOOGLE_CLOUD_PROJECT, datasetName, tableName, firstRole, identity); - GrantAccessToTableOrView.grantAccessToTableOrView( + Util.setUpTest_grantAccessToTableOrView( GOOGLE_CLOUD_PROJECT, datasetName, viewName, firstRole, identity); // Add a second role for identity. secondRole = Role.of("roles/bigquery.dataEditor"); // Grant access to table and view. - GrantAccessToTableOrView.grantAccessToTableOrView( + Util.setUpTest_grantAccessToTableOrView( GOOGLE_CLOUD_PROJECT, datasetName, tableName, secondRole, identity); - GrantAccessToTableOrView.grantAccessToTableOrView( + Util.setUpTest_grantAccessToTableOrView( GOOGLE_CLOUD_PROJECT, datasetName, viewName, secondRole, identity); } diff --git a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/Util.java b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/Util.java index b25e10e5a22..90649e13499 100644 --- a/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/Util.java +++ b/bigquery/cloud-client/snippets/src/test/java/com/example/bigquery/Util.java @@ -16,6 +16,9 @@ package com.example.bigquery; +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.Role; import com.google.cloud.bigquery.BigQuery; import com.google.cloud.bigquery.BigQuery.DatasetDeleteOption; import com.google.cloud.bigquery.BigQueryException; @@ -73,4 +76,14 @@ public static boolean tearDownTest_deleteTableOrView( TableId tableId = TableId.of(projectId, datasetName, tableName); return bigquery.delete(tableId); } + + public static Policy setUpTest_grantAccessToTableOrView( + String projectId, String datasetName, String resourceName, Role role, Identity identity) + throws BigQueryException { + TableId tableId = TableId.of(projectId, datasetName, resourceName); + Policy policy = bigquery.getIamPolicy(tableId); + policy = policy.toBuilder().addIdentity(role, identity).build(); + + return bigquery.setIamPolicy(tableId, policy); + } } From e6b084c53561d10d65e3675d27e7aafa14a6eb0f Mon Sep 17 00:00:00 2001 From: Francisco Javier Alarcon Esparza Date: Wed, 12 Mar 2025 17:07:40 +0000 Subject: [PATCH 4/5] fix typo --- .../java/com/example/bigquery/RevokeAccessToTableOrView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java index f48db2842dd..f39734f3f60 100644 --- a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java +++ b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java @@ -68,7 +68,7 @@ public static void revokeAccessToTableOrView( // Remove one identity in all the existing roles. for (Role roleKey : bindings.keySet()) { if (bindings.get(roleKey).contains(identity)) { - // Create a copy of a inmutable set if the identity is present in the role. + // Create a copy of an immutable set if the identity is present in the role. Set identities = new HashSet<>(bindings.get(roleKey)); // Remove identity. identities.remove(identity); From 833d51cd9fe54dbb3f08c856e5e430d5f11d907c Mon Sep 17 00:00:00 2001 From: Francisco Javier Alarcon Esparza Date: Wed, 12 Mar 2025 17:30:52 +0000 Subject: [PATCH 5/5] fix typo --- .../java/com/example/bigquery/RevokeAccessToTableOrView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java index f39734f3f60..0a9b30b5404 100644 --- a/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java +++ b/bigquery/cloud-client/snippets/src/main/java/com/example/bigquery/RevokeAccessToTableOrView.java @@ -57,7 +57,7 @@ public static void revokeAccessToTableOrView( // Remove either identities or roles, or both from bindings and replace it in // the current IAM policy. Policy policy = bigquery.getIamPolicy(tableId); - // Create a copy of a inmutable map. + // Create a copy of an immutable map. Map> bindings = new HashMap<>(policy.getBindings()); // Remove all identities with a specific role.