diff --git a/.github/snippet-bot.yml b/.github/snippet-bot.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.github/workflows/approve-readme.yaml b/.github/workflows/approve-readme.yaml new file mode 100644 index 0000000000..e2d841d6c5 --- /dev/null +++ b/.github/workflows/approve-readme.yaml @@ -0,0 +1,54 @@ +on: + pull_request: +name: auto-merge-readme +jobs: + approve: + runs-on: ubuntu-latest + if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' + steps: + - uses: actions/github-script@v3.0.0 + with: + github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} + script: | + // only approve PRs from yoshi-automation + if (context.payload.pull_request.user.login !== "yoshi-automation") { + return; + } + + // only approve PRs like "chore: release " + if (!context.payload.pull_request.title === "chore: regenerate README") { + return; + } + + // only approve PRs with README.md and synth.metadata changes + const files = new Set( + ( + await github.paginate( + github.pulls.listFiles.endpoint({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + }) + ) + ).map(file => file.filename) + ); + if (files.size != 2 || !files.has("README.md") || !files.has(".github/readme/synth.metadata/synth.metadata")) { + return; + } + + // approve README regeneration PR + await github.pulls.createReview({ + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Rubber stamped PR!', + pull_number: context.payload.pull_request.number, + event: 'APPROVE' + }); + + // attach automerge label + await github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ['automerge'] + }); diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f2e56f769..8b2e4c9e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [1.17.0](https://www.github.com/googleapis/java-bigtable/compare/v1.16.2...v1.17.0) (2020-10-23) + + +### Features + +* attemp DirectPath by default ([#467](https://www.github.com/googleapis/java-bigtable/issues/467)) ([89c622d](https://www.github.com/googleapis/java-bigtable/commit/89c622da6038067892687af3edafae743465eda7)) +* backup level IAM ([#450](https://www.github.com/googleapis/java-bigtable/issues/450)) ([f38a8ec](https://www.github.com/googleapis/java-bigtable/commit/f38a8ecdc6164d081ef96f748ea37bd62b29b419)) +* Implement toString for Bigtable*Settings ([#488](https://www.github.com/googleapis/java-bigtable/issues/488)) ([4d821f8](https://www.github.com/googleapis/java-bigtable/commit/4d821f85ceb237c8e449243ff8c80fb94e22ad51)) + + +### Bug Fixes + +* Make refreshing channel compatible with BigtableDataClientFactory ([#474](https://www.github.com/googleapis/java-bigtable/issues/474)) ([fc74164](https://www.github.com/googleapis/java-bigtable/commit/fc741645536e01fac772136bc8346f73ff95e600)) + + +### Documentation + +* fix formatting ([#476](https://www.github.com/googleapis/java-bigtable/issues/476)) ([eb24569](https://www.github.com/googleapis/java-bigtable/commit/eb24569e53f9d2b7fde50748c840c2c11f3f3c80)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.12.1 ([#475](https://www.github.com/googleapis/java-bigtable/issues/475)) ([9e56edf](https://www.github.com/googleapis/java-bigtable/commit/9e56edfa7b0a78f14518a99130a7b319c5873be4)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.13.0 ([#484](https://www.github.com/googleapis/java-bigtable/issues/484)) ([aad648f](https://www.github.com/googleapis/java-bigtable/commit/aad648fec16b122092d394350822da742a2d7aa0)) +* update dependency com.google.truth:truth to v1.1 ([#483](https://www.github.com/googleapis/java-bigtable/issues/483)) ([cca1e0e](https://www.github.com/googleapis/java-bigtable/commit/cca1e0e16f2ec0cc887d81c1844f5395ce08b6ea)) + ### [1.16.2](https://www.github.com/googleapis/java-bigtable/compare/v1.16.1...v1.16.2) (2020-10-14) diff --git a/README.md b/README.md index e515055ff9..28d7999c83 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-bigtable - 1.16.2 + 1.17.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-bigtable:1.16.2' +compile 'com.google.cloud:google-cloud-bigtable:1.17.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "1.16.2" +libraryDependencies += "com.google.cloud" % "google-cloud-bigtable" % "1.17.0" ``` [//]: # ({x-version-update-end}) diff --git a/google-cloud-bigtable-bom/pom.xml b/google-cloud-bigtable-bom/pom.xml index ead7580e36..bbbc930bf6 100644 --- a/google-cloud-bigtable-bom/pom.xml +++ b/google-cloud-bigtable-bom/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom com.google.cloud google-cloud-shared-config - 0.9.2 + 0.9.3 Google Cloud Bigtable BOM @@ -72,32 +72,32 @@ com.google.cloud google-cloud-bigtable - 1.16.2 + 1.17.0 com.google.cloud google-cloud-bigtable-emulator - 0.125.2 + 0.126.0 com.google.api.grpc grpc-google-cloud-bigtable-admin-v2 - 1.16.2 + 1.17.0 com.google.api.grpc grpc-google-cloud-bigtable-v2 - 1.16.2 + 1.17.0 com.google.api.grpc proto-google-cloud-bigtable-admin-v2 - 1.16.2 + 1.17.0 com.google.api.grpc proto-google-cloud-bigtable-v2 - 1.16.2 + 1.17.0 diff --git a/google-cloud-bigtable-deps-bom/pom.xml b/google-cloud-bigtable-deps-bom/pom.xml index 986c302d00..82b15bccfa 100644 --- a/google-cloud-bigtable-deps-bom/pom.xml +++ b/google-cloud-bigtable-deps-bom/pom.xml @@ -7,12 +7,12 @@ com.google.cloud google-cloud-shared-config - 0.9.2 + 0.9.3 com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom @@ -79,7 +79,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.11.0 + 0.13.0 pom import diff --git a/google-cloud-bigtable-emulator/pom.xml b/google-cloud-bigtable-emulator/pom.xml index 930b32be08..9e16d8619b 100644 --- a/google-cloud-bigtable-emulator/pom.xml +++ b/google-cloud-bigtable-emulator/pom.xml @@ -5,7 +5,7 @@ 4.0.0 google-cloud-bigtable-emulator - 0.125.2 + 0.126.0 Google Cloud Java - Bigtable Emulator https://github.com/googleapis/java-bigtable @@ -14,7 +14,7 @@ com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 scm:git:git@github.com:googleapis/java-bigtable.git @@ -80,14 +80,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import diff --git a/google-cloud-bigtable/pom.xml b/google-cloud-bigtable/pom.xml index 3a7d26ce52..6389aad2ba 100644 --- a/google-cloud-bigtable/pom.xml +++ b/google-cloud-bigtable/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-bigtable - 1.16.2 + 1.17.0 jar Google Cloud Bigtable https://github.com/googleapis/java-bigtable @@ -12,9 +12,12 @@ com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 + + 1.17.0 + google-cloud-bigtable + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import @@ -383,7 +386,36 @@ + + + src/main/templates + + **/*.java + + true + ${project.build.directory}/generated-sources/java + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/java/ + + + + + org.apache.maven.plugins maven-enforcer-plugin diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettings.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettings.java index f7f045c23a..f89142828d 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettings.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettings.java @@ -19,6 +19,7 @@ import com.google.api.gax.core.CredentialsProvider; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStubSettings; +import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Verify; import java.io.IOException; @@ -74,6 +75,39 @@ public BigtableInstanceAdminStubSettings getStubSettings() { return stubSettings; } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("projectId", projectId) + .add("createInstanceSettings", stubSettings.createInstanceSettings()) + .add("createInstanceOperationSettings", stubSettings.createInstanceOperationSettings()) + .add("getInstanceSettings", stubSettings.getInstanceSettings()) + .add("listInstancesSettings", stubSettings.listInstancesSettings()) + .add("partialUpdateInstanceSettings", stubSettings.partialUpdateInstanceSettings()) + .add( + "partialUpdateInstanceOperationSettings", + stubSettings.partialUpdateInstanceOperationSettings()) + .add("deleteInstanceSettings", stubSettings.deleteInstanceSettings()) + .add("createClusterSettings", stubSettings.createClusterSettings()) + .add("createClusterOperationSettings", stubSettings.createClusterOperationSettings()) + .add("getClusterSettings", stubSettings.getClusterSettings()) + .add("listClustersSettings", stubSettings.listClustersSettings()) + .add("updateClusterSettings", stubSettings.updateClusterSettings()) + .add("updateClusterOperationSettings", stubSettings.updateClusterOperationSettings()) + .add("deleteClusterSettings", stubSettings.deleteClusterSettings()) + .add("createAppProfileSettings", stubSettings.createAppProfileSettings()) + .add("getAppProfileSettings", stubSettings.getAppProfileSettings()) + .add("listAppProfilesSettings", stubSettings.listAppProfilesSettings()) + .add("updateAppProfileSettings", stubSettings.updateAppProfileSettings()) + .add("updateAppProfileOperationSettings", stubSettings.updateAppProfileOperationSettings()) + .add("deleteAppProfileSettings", stubSettings.deleteAppProfileSettings()) + .add("getIamPolicySettings", stubSettings.getIamPolicySettings()) + .add("setIamPolicySettings", stubSettings.setIamPolicySettings()) + .add("testIamPermissionsSettings", stubSettings.testIamPermissionsSettings()) + .add("stubSettings", stubSettings) + .toString(); + } + /** Returns a builder containing all the values of this settings class. */ public Builder toBuilder() { return new Builder(this); diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java index 5d0350b9cf..d4029e19b5 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClient.java @@ -1319,21 +1319,8 @@ public Policy getIamPolicy(String tableId) { */ @SuppressWarnings("WeakerAccess") public ApiFuture getIamPolicyAsync(String tableId) { - String name = NameUtil.formatTableName(projectId, instanceId, tableId); - - GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder().setResource(name).build(); - - final IamPolicyMarshaller marshaller = new IamPolicyMarshaller(); - - return ApiFutures.transform( - stub.getIamPolicyCallable().futureCall(request), - new ApiFunction() { - @Override - public Policy apply(com.google.iam.v1.Policy proto) { - return marshaller.fromPb(proto); - } - }, - MoreExecutors.directExecutor()); + String tableName = NameUtil.formatTableName(projectId, instanceId, tableId); + return getResourceIamPolicy(tableName); } /** @@ -1391,24 +1378,8 @@ public Policy setIamPolicy(String tableId, Policy policy) { */ @SuppressWarnings("WeakerAccess") public ApiFuture setIamPolicyAsync(String tableId, Policy policy) { - String name = NameUtil.formatTableName(projectId, instanceId, tableId); - final IamPolicyMarshaller marshaller = new IamPolicyMarshaller(); - - SetIamPolicyRequest request = - SetIamPolicyRequest.newBuilder() - .setResource(name) - .setPolicy(marshaller.toPb(policy)) - .build(); - - return ApiFutures.transform( - stub.setIamPolicyCallable().futureCall(request), - new ApiFunction() { - @Override - public Policy apply(com.google.iam.v1.Policy proto) { - return marshaller.fromPb(proto); - } - }, - MoreExecutors.directExecutor()); + String tableName = NameUtil.formatTableName(projectId, instanceId, tableId); + return setResourceIamPolicy(policy, tableName); } /** @@ -1463,9 +1434,227 @@ public List testIamPermission(String tableId, String... permissions) { */ @SuppressWarnings({"WeakerAccess"}) public ApiFuture> testIamPermissionAsync(String tableId, String... permissions) { + String tableName = NameUtil.formatTableName(projectId, instanceId, tableId); + return testResourceIamPermissions(tableName, permissions); + } + + /** + * Gets the IAM access control policy for the specified backup. + * + *

Sample code: + * + *

{@code
+   * Policy policy = client.getBackupIamPolicy("my-cluster-id", "my-backup-id");
+   * for(Map.Entry> entry : policy.getBindings().entrySet()) {
+   *   System.out.printf("Role: %s Identities: %s\n", entry.getKey(), entry.getValue());
+   * }
+   * }
+ * + * @see Table-level + * IAM management + */ + @SuppressWarnings("WeakerAccess") + public Policy getBackupIamPolicy(String clusterId, String backupId) { + return ApiExceptions.callAndTranslateApiException(getBackupIamPolicyAsync(clusterId, backupId)); + } + + /** + * Asynchronously gets the IAM access control policy for the specified backup. + * + *

Sample code: + * + *

{@code
+   * ApiFuture policyFuture = client.getBackupIamPolicyAsync("my-cluster-id", "my-backup-id");
+   *
+   * ApiFutures.addCallback(policyFuture,
+   *   new ApiFutureCallback() {
+   *     public void onSuccess(Policy policy) {
+   *       for (Entry> entry : policy.getBindings().entrySet()) {
+   *         System.out.printf("Role: %s Identities: %s\n", entry.getKey(), entry.getValue());
+   *       }
+   *     }
+   *
+   *     public void onFailure(Throwable t) {
+   *       t.printStackTrace();
+   *     }
+   *   },
+   *   MoreExecutors.directExecutor());
+   * }
+ * + * @see Table-level + * IAM management + */ + @SuppressWarnings("WeakerAccess") + public ApiFuture getBackupIamPolicyAsync(String clusterId, String backupId) { + String backupName = NameUtil.formatBackupName(projectId, instanceId, clusterId, backupId); + return getResourceIamPolicy(backupName); + } + + /** + * Replaces the IAM policy associated with the specified backup. + * + *

Sample code: + * + *

{@code
+   * Policy newPolicy = client.setBackupIamPolicy("my-cluster-id", "my-backup-id",
+   *   Policy.newBuilder()
+   *     .addIdentity(Role.of("bigtable.user"), Identity.user("someone@example.com"))
+   *     .addIdentity(Role.of("bigtable.admin"), Identity.group("admins@example.com"))
+   *     .build());
+   * }
+ * + * @see Table-level + * IAM management + */ + @SuppressWarnings("WeakerAccess") + public Policy setBackupIamPolicy(String clusterId, String backupId, Policy policy) { + return ApiExceptions.callAndTranslateApiException( + setBackupIamPolicyAsync(clusterId, backupId, policy)); + } + + /** + * Asynchronously replaces the IAM policy associated with the specified backup. + * + *

Sample code: + * + *

{@code
+   * ApiFuture newPolicyFuture = client.setBackupIamPolicyAsync("my-cluster-id", "my-backup-id",
+   *   Policy.newBuilder()
+   *     .addIdentity(Role.of("bigtable.user"), Identity.user("someone@example.com"))
+   *     .addIdentity(Role.of("bigtable.admin"), Identity.group("admins@example.com"))
+   *     .build());
+   *
+   * ApiFutures.addCallback(newPolicyFuture,
+   *   new ApiFutureCallback() {
+   *     public void onSuccess(Policy policy) {
+   *       for (Entry> entry : policy.getBindings().entrySet()) {
+   *         System.out.printf("Role: %s Identities: %s\n", entry.getKey(), entry.getValue());
+   *       }
+   *     }
+   *
+   *     public void onFailure(Throwable t) {
+   *       t.printStackTrace();
+   *     }
+   *   },
+   *   MoreExecutors.directExecutor());
+   * }
+ * + * @see Table-level + * IAM management + */ + @SuppressWarnings("WeakerAccess") + public ApiFuture setBackupIamPolicyAsync( + String clusterId, String backupId, Policy policy) { + String backupName = NameUtil.formatBackupName(projectId, instanceId, clusterId, backupId); + return setResourceIamPolicy(policy, backupName); + } + + /** + * Tests whether the caller has the given permissions for the specified backup. Returns a subset + * of the specified permissions that the caller has. + * + *

Sample code: + * + *

{@code
+   * List grantedPermissions = client.testBackupIamPermission("my-cluster-id", "my-backup-id",
+   *   "bigtable.backups.restore", "bigtable.backups.delete");
+   * }
+ * + * System.out.println("Has restore access: " + + * grantedPermissions.contains("bigtable.backups.restore")); + * + *

System.out.println("Has delete access: " + + * grantedPermissions.contains("bigtable.backups.delete")); + * + * @see Cloud Bigtable + * permissions + */ + @SuppressWarnings({"WeakerAccess"}) + public List testBackupIamPermission( + String clusterId, String backupId, String... permissions) { + return ApiExceptions.callAndTranslateApiException( + testBackupIamPermissionAsync(clusterId, backupId, permissions)); + } + + /** + * Asynchronously tests whether the caller has the given permissions for the specified backup. + * Returns a subset of the specified permissions that the caller has. + * + *

Sample code: + * + *

{@code
+   * ApiFuture> grantedPermissionsFuture = client.testBackupIamPermissionAsync("my-cluster-id", "my-backup-id",
+   *   "bigtable.backups.restore", "bigtable.backups.delete");
+   *
+   * ApiFutures.addCallback(grantedPermissionsFuture,
+   *   new ApiFutureCallback>() {
+   *     public void onSuccess(List grantedPermissions) {
+   *       System.out.println("Has restore access: " + grantedPermissions.contains("bigtable.backups.restore"));
+   *       System.out.println("Has delete access: " + grantedPermissions.contains("bigtable.backups.delete"));
+   *     }
+   *
+   *     public void onFailure(Throwable t) {
+   *       t.printStackTrace();
+   *     }
+   *   },
+   *   MoreExecutors.directExecutor());
+   * }
+ * + * @see Cloud Bigtable + * permissions + */ + @SuppressWarnings({"WeakerAccess"}) + public ApiFuture> testBackupIamPermissionAsync( + String clusterId, String backupId, String... permissions) { + String backupName = NameUtil.formatBackupName(projectId, instanceId, clusterId, backupId); + return testResourceIamPermissions(backupName, permissions); + } + + private ApiFuture getResourceIamPolicy(String name) { + GetIamPolicyRequest request = GetIamPolicyRequest.newBuilder().setResource(name).build(); + + final IamPolicyMarshaller marshaller = new IamPolicyMarshaller(); + + return ApiFutures.transform( + stub.getIamPolicyCallable().futureCall(request), + new ApiFunction() { + @Override + public Policy apply(com.google.iam.v1.Policy proto) { + return marshaller.fromPb(proto); + } + }, + MoreExecutors.directExecutor()); + } + + private ApiFuture setResourceIamPolicy(Policy policy, String name) { + final IamPolicyMarshaller marshaller = new IamPolicyMarshaller(); + + SetIamPolicyRequest request = + SetIamPolicyRequest.newBuilder() + .setResource(name) + .setPolicy(marshaller.toPb(policy)) + .build(); + + return ApiFutures.transform( + stub.setIamPolicyCallable().futureCall(request), + new ApiFunction() { + @Override + public Policy apply(com.google.iam.v1.Policy proto) { + return marshaller.fromPb(proto); + } + }, + MoreExecutors.directExecutor()); + } + + private ApiFuture> testResourceIamPermissions( + String resourceName, String[] permissions) { TestIamPermissionsRequest request = TestIamPermissionsRequest.newBuilder() - .setResource(NameUtil.formatTableName(projectId, instanceId, tableId)) + .setResource(resourceName) .addAllPermissions(Arrays.asList(permissions)) .build(); diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettings.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettings.java index 5729372a2a..9cba1159b9 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettings.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettings.java @@ -20,6 +20,7 @@ import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; +import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.base.Verify; @@ -85,6 +86,43 @@ public BigtableTableAdminStubSettings getStubSettings() { return stubSettings; } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("projectId", projectId) + .add("instanceId", instanceId) + .add("createTableSettings", stubSettings.createTableSettings()) + .add("createTableFromSnapshotSettings", stubSettings.createTableFromSnapshotSettings()) + .add( + "createTableFromSnapshotOperationSettings", + stubSettings.createTableFromSnapshotOperationSettings()) + .add("listTablesSettings", stubSettings.listTablesSettings()) + .add("getTableSettings", stubSettings.getTableSettings()) + .add("deleteTableSettings", stubSettings.deleteTableSettings()) + .add("modifyColumnFamiliesSettings", stubSettings.modifyColumnFamiliesSettings()) + .add("dropRowRangeSettings", stubSettings.dropRowRangeSettings()) + .add("generateConsistencyTokenSettings", stubSettings.generateConsistencyTokenSettings()) + .add("checkConsistencySettings", stubSettings.checkConsistencySettings()) + .add("getIamPolicySettings", stubSettings.getIamPolicySettings()) + .add("setIamPolicySettings", stubSettings.setIamPolicySettings()) + .add("testIamPermissionsSettings", stubSettings.testIamPermissionsSettings()) + .add("snapshotTableSettings", stubSettings.snapshotTableSettings()) + .add("snapshotTableOperationSettings", stubSettings.snapshotTableOperationSettings()) + .add("getSnapshotSettings", stubSettings.getSnapshotSettings()) + .add("listSnapshotsSettings", stubSettings.listSnapshotsSettings()) + .add("deleteSnapshotSettings", stubSettings.deleteSnapshotSettings()) + .add("createBackupSettings", stubSettings.createBackupSettings()) + .add("createBackupOperationSettings", stubSettings.createBackupOperationSettings()) + .add("getBackupSettings", stubSettings.getBackupSettings()) + .add("listBackupsSettings", stubSettings.listBackupsSettings()) + .add("updateBackupSettings", stubSettings.updateBackupSettings()) + .add("deleteBackupSettings", stubSettings.deleteBackupSettings()) + .add("restoreTableSettings", stubSettings.restoreTableSettings()) + .add("restoreTableOperationSettings", stubSettings.restoreTableOperationSettings()) + .add("stubSettings", stubSettings) + .toString(); + } + /** Returns a builder containing all the values of this settings class. */ public Builder toBuilder() { return new Builder(this); diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java index b08613cc69..d4561ab4df 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactory.java @@ -23,7 +23,7 @@ import com.google.api.gax.rpc.FixedHeaderProvider; import com.google.api.gax.rpc.FixedTransportChannelProvider; import com.google.api.gax.rpc.FixedWatchdogProvider; -import com.google.api.gax.rpc.StubSettings; +import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings; import java.io.IOException; import javax.annotation.Nonnull; @@ -189,8 +189,11 @@ public BigtableDataClient createForInstance( } // Update stub settings to use shared resources in this factory - private void patchStubSettings(StubSettings.Builder stubSettings) { + private void patchStubSettings(EnhancedBigtableStubSettings.Builder stubSettings) { stubSettings + // Channel refreshing will be configured in the shared ClientContext. Derivative clients + // won't be able to reconfigure the refreshing logic + .setRefreshingChannel(false) .setTransportChannelProvider( FixedTransportChannelProvider.create(sharedClientContext.getTransportChannel())) .setCredentialsProvider( diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java index 3b07eeaf23..105fbaae45 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/BigtableDataSettings.java @@ -24,6 +24,7 @@ import com.google.cloud.bigtable.data.v2.models.Query; import com.google.cloud.bigtable.data.v2.models.Row; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings; +import com.google.common.base.MoreObjects; import com.google.common.base.Strings; import io.grpc.ManagedChannelBuilder; import java.util.List; @@ -215,6 +216,11 @@ public UnaryCallSettings readRowSettings() { return stubSettings.readRowSettings(); } + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("stubSettings", stubSettings).toString(); + } + /** Returns a builder containing all the values of this settings class. */ public Builder toBuilder() { return new Builder(this); diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettings.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettings.java index 360141083e..1593ce8d48 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettings.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettings.java @@ -20,7 +20,7 @@ import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.batching.FlowControlSettings; import com.google.api.gax.batching.FlowController.LimitExceededBehavior; -import com.google.api.gax.core.GaxProperties; +import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.RetrySettings; @@ -30,6 +30,8 @@ import com.google.api.gax.rpc.StubSettings; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.UnaryCallSettings; +import com.google.auth.Credentials; +import com.google.cloud.bigtable.Version; import com.google.cloud.bigtable.data.v2.models.ConditionalRowMutation; import com.google.cloud.bigtable.data.v2.models.KeyOffset; import com.google.cloud.bigtable.data.v2.models.Query; @@ -38,10 +40,12 @@ import com.google.cloud.bigtable.data.v2.models.RowMutation; import com.google.cloud.bigtable.data.v2.stub.mutaterows.MutateRowsBatchingDescriptor; import com.google.cloud.bigtable.data.v2.stub.readrows.ReadRowsBatchingDescriptor; +import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; @@ -85,9 +89,6 @@ public class EnhancedBigtableStubSettings extends StubSettings IDEMPOTENT_RETRY_CODES = ImmutableSet.of(Code.DEADLINE_EXCEEDED, Code.UNAVAILABLE); @@ -166,12 +167,6 @@ public class EnhancedBigtableStubSettings extends StubSettings } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("projectId", projectId) + .add("instanceId", instanceId) + .add("appProfileId", appProfileId) + .add("isRefreshingChannel", isRefreshingChannel) + .add("primedTableIds", primedTableIds) + .add("readRowsSettings", readRowsSettings) + .add("readRowSettings", readRowSettings) + .add("sampleRowKeysSettings", sampleRowKeysSettings) + .add("mutateRowSettings", mutateRowSettings) + .add("bulkMutateRowsSettings", bulkMutateRowsSettings) + .add("bulkReadRowsSettings", bulkReadRowsSettings) + .add("checkAndMutateRowSettings", checkAndMutateRowSettings) + .add("readModifyWriteRowSettings", readModifyWriteRowSettings) + .add("parent", super.toString()) + .toString(); + } } diff --git a/google-cloud-bigtable/src/main/templates/com/google/cloud/bigtable/Version.java b/google-cloud-bigtable/src/main/templates/com/google/cloud/bigtable/Version.java new file mode 100644 index 0000000000..7f87f249dc --- /dev/null +++ b/google-cloud-bigtable/src/main/templates/com/google/cloud/bigtable/Version.java @@ -0,0 +1,24 @@ +/* + * Copyright 2020 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 + * + * https://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.google.cloud.bigtable; + +import com.google.api.core.InternalApi; + +@InternalApi("For internal use only") +public final class Version { + // The released version, populated by maven. + public static String VERSION = "${java-bigtable.version}"; +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettingsTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettingsTest.java index c6ccf9557b..fd761ff915 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettingsTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettingsTest.java @@ -18,12 +18,15 @@ import static com.google.common.truth.Truth.assertThat; import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.StatusCode.Code; +import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStubSettings; import java.io.IOException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mockito; +import org.threeten.bp.Duration; @RunWith(JUnit4.class) public class BigtableInstanceAdminSettingsTest { @@ -95,4 +98,63 @@ public void testStubSettings() throws IOException { .getRetryableCodes()) .containsExactly(Code.INVALID_ARGUMENT); } + + static final String[] SETTINGS_LIST = { + "createInstanceSettings", + "createInstanceOperationSettings", + "getInstanceSettings", + "listInstancesSettings", + "partialUpdateInstanceSettings", + "partialUpdateInstanceOperationSettings", + "deleteInstanceSettings", + "createClusterSettings", + "createClusterOperationSettings", + "getClusterSettings", + "listClustersSettings", + "updateClusterSettings", + "updateClusterOperationSettings", + "deleteClusterSettings", + "createAppProfileSettings", + "getAppProfileSettings", + "listAppProfilesSettings", + "updateAppProfileSettings", + "updateAppProfileOperationSettings", + "deleteAppProfileSettings", + "getIamPolicySettings", + "setIamPolicySettings", + "testIamPermissionsSettings", + }; + + @Test + public void testToString() throws IOException { + BigtableInstanceAdminSettings defaultSettings = + BigtableInstanceAdminSettings.newBuilder().setProjectId("our-project-212").build(); + + checkToString(defaultSettings); + + BigtableInstanceAdminSettings.Builder builder = defaultSettings.toBuilder(); + BigtableInstanceAdminStubSettings.Builder stubSettings = + builder.stubSettings().setEndpoint("example.com:1234"); + + stubSettings + .getInstanceSettings() + .setRetrySettings( + RetrySettings.newBuilder().setTotalTimeout(Duration.ofMinutes(812)).build()); + + BigtableInstanceAdminSettings settings = builder.build(); + checkToString(settings); + assertThat(settings.toString()).contains("endpoint=example.com:1234"); + assertThat(settings.toString()).contains("totalTimeout=PT13H32M"); + } + + void checkToString(BigtableInstanceAdminSettings settings) { + String projectId = settings.getProjectId(); + String toString = settings.toString(); + assertThat(toString).isEqualTo(settings.toString()); // no variety + assertThat(toString).startsWith("BigtableInstanceAdminSettings{projectId=" + projectId); + for (String subSettings : SETTINGS_LIST) { + assertThat(toString).contains(subSettings + "="); + } + assertThat(toString.contains(settings.getStubSettings().toString())); + } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientTest.java index c265514325..eeb87ada2d 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminClientTest.java @@ -44,6 +44,9 @@ import com.google.bigtable.admin.v2.RestoreTableMetadata; import com.google.bigtable.admin.v2.Table.View; import com.google.bigtable.admin.v2.TableName; +import com.google.cloud.Identity; +import com.google.cloud.Policy; +import com.google.cloud.Role; import com.google.cloud.bigtable.admin.v2.BaseBigtableTableAdminClient.ListBackupsPage; import com.google.cloud.bigtable.admin.v2.BaseBigtableTableAdminClient.ListBackupsPagedResponse; import com.google.cloud.bigtable.admin.v2.BaseBigtableTableAdminClient.ListTablesPage; @@ -59,6 +62,7 @@ import com.google.cloud.bigtable.admin.v2.models.UpdateBackupRequest; import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; import com.google.common.collect.Lists; +import com.google.common.io.BaseEncoding; import com.google.longrunning.Operation; import com.google.protobuf.Any; import com.google.protobuf.ByteString; @@ -94,7 +98,6 @@ public class BigtableTableAdminClientTest { private static final String CLUSTER_ID = "my-cluster"; private static final String BACKUP_ID = "my-backup"; - private static final String PROJECT_NAME = NameUtil.formatProjectName(PROJECT_ID); private static final String INSTANCE_NAME = NameUtil.formatInstanceName(PROJECT_ID, INSTANCE_ID); private static final String TABLE_NAME = NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, TABLE_ID); @@ -156,6 +159,19 @@ public class BigtableTableAdminClientTest { RestoreTableMetadata> mockRestoreTableOperationCallable; + @Mock + private UnaryCallable + mockGetIamPolicyCallable; + + @Mock + private UnaryCallable + mockSetIamPolicyCallable; + + @Mock + private UnaryCallable< + com.google.iam.v1.TestIamPermissionsRequest, com.google.iam.v1.TestIamPermissionsResponse> + mockTestIamPermissionsCallable; + @Before public void setUp() { adminClient = BigtableTableAdminClient.create(PROJECT_ID, INSTANCE_ID, mockStub); @@ -177,6 +193,9 @@ public void setUp() { Mockito.when(mockStub.restoreTableCallable()).thenReturn(mockRestoreTableCallable); Mockito.when(mockStub.restoreTableOperationCallable()) .thenReturn(mockRestoreTableOperationCallable); + Mockito.when(mockStub.getIamPolicyCallable()).thenReturn(mockGetIamPolicyCallable); + Mockito.when(mockStub.setIamPolicyCallable()).thenReturn(mockSetIamPolicyCallable); + Mockito.when(mockStub.testIamPermissionsCallable()).thenReturn(mockTestIamPermissionsCallable); } @Test @@ -645,6 +664,107 @@ public void testListBackups() { assertThat(actualResults).containsExactlyElementsIn(expectedResults); } + @Test + public void testGetBackupIamPolicy() { + // Setup + com.google.iam.v1.GetIamPolicyRequest expectedRequest = + com.google.iam.v1.GetIamPolicyRequest.newBuilder() + .setResource(NameUtil.formatBackupName(PROJECT_ID, INSTANCE_ID, CLUSTER_ID, BACKUP_ID)) + .build(); + + com.google.iam.v1.Policy expectedResponse = + com.google.iam.v1.Policy.newBuilder() + .addBindings( + com.google.iam.v1.Binding.newBuilder() + .setRole("roles/bigtable.viewer") + .addMembers("user:someone@example.com")) + .setEtag(ByteString.copyFromUtf8("my-etag")) + .build(); + + Mockito.when(mockGetIamPolicyCallable.futureCall(expectedRequest)) + .thenReturn(ApiFutures.immediateFuture(expectedResponse)); + + // Execute + Policy actualResult = adminClient.getBackupIamPolicy(CLUSTER_ID, BACKUP_ID); + + // Verify + assertThat(actualResult) + .isEqualTo( + Policy.newBuilder() + .addIdentity(Role.of("bigtable.viewer"), Identity.user("someone@example.com")) + .setEtag(BaseEncoding.base64().encode("my-etag".getBytes())) + .build()); + } + + @Test + public void testSetIamPolicy() { + // Setup + com.google.iam.v1.SetIamPolicyRequest expectedRequest = + com.google.iam.v1.SetIamPolicyRequest.newBuilder() + .setResource(NameUtil.formatBackupName(PROJECT_ID, INSTANCE_ID, CLUSTER_ID, BACKUP_ID)) + .setPolicy( + com.google.iam.v1.Policy.newBuilder() + .addBindings( + com.google.iam.v1.Binding.newBuilder() + .setRole("roles/bigtable.viewer") + .addMembers("user:someone@example.com"))) + .build(); + + com.google.iam.v1.Policy expectedResponse = + com.google.iam.v1.Policy.newBuilder() + .addBindings( + com.google.iam.v1.Binding.newBuilder() + .setRole("roles/bigtable.viewer") + .addMembers("user:someone@example.com")) + .setEtag(ByteString.copyFromUtf8("my-etag")) + .build(); + + Mockito.when(mockSetIamPolicyCallable.futureCall(expectedRequest)) + .thenReturn(ApiFutures.immediateFuture(expectedResponse)); + + // Execute + Policy actualResult = + adminClient.setBackupIamPolicy( + CLUSTER_ID, + BACKUP_ID, + Policy.newBuilder() + .addIdentity(Role.of("bigtable.viewer"), Identity.user("someone@example.com")) + .build()); + + // Verify + assertThat(actualResult) + .isEqualTo( + Policy.newBuilder() + .addIdentity(Role.of("bigtable.viewer"), Identity.user("someone@example.com")) + .setEtag(BaseEncoding.base64().encode("my-etag".getBytes())) + .build()); + } + + @Test + public void testTestIamPermissions() { + // Setup + com.google.iam.v1.TestIamPermissionsRequest expectedRequest = + com.google.iam.v1.TestIamPermissionsRequest.newBuilder() + .setResource(NameUtil.formatBackupName(PROJECT_ID, INSTANCE_ID, CLUSTER_ID, BACKUP_ID)) + .addPermissions("bigtable.backups.get") + .build(); + + com.google.iam.v1.TestIamPermissionsResponse expectedResponse = + com.google.iam.v1.TestIamPermissionsResponse.newBuilder() + .addPermissions("bigtable.backups.get") + .build(); + + Mockito.when(mockTestIamPermissionsCallable.futureCall(expectedRequest)) + .thenReturn(ApiFutures.immediateFuture(expectedResponse)); + + // Execute + List actualResult = + adminClient.testBackupIamPermission(CLUSTER_ID, BACKUP_ID, "bigtable.backups.get"); + + // Verify + assertThat(actualResult).containsExactly("bigtable.backups.get"); + } + private void mockOperationResult( OperationCallable callable, ReqT request, diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettingsTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettingsTest.java index 77ce733ce0..773bd56665 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettingsTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableTableAdminSettingsTest.java @@ -18,12 +18,17 @@ import static com.google.common.truth.Truth.assertThat; import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.StatusCode.Code; +import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mockito; +import org.threeten.bp.Duration; @RunWith(JUnit4.class) public class BigtableTableAdminSettingsTest { @@ -97,4 +102,83 @@ public void testStubSettings() throws IOException { .getRetryableCodes()) .containsExactly(Code.INVALID_ARGUMENT); } + + static final String[] SETTINGS_LIST = { + "createTableSettings", + "createTableFromSnapshotSettings", + "createTableFromSnapshotOperationSettings", + "listTablesSettings", + "getTableSettings", + "deleteTableSettings", + "modifyColumnFamiliesSettings", + "dropRowRangeSettings", + "generateConsistencyTokenSettings", + "checkConsistencySettings", + "getIamPolicySettings", + "setIamPolicySettings", + "testIamPermissionsSettings", + "snapshotTableSettings", + "snapshotTableOperationSettings", + "getSnapshotSettings", + "listSnapshotsSettings", + "deleteSnapshotSettings", + "createBackupSettings", + "createBackupOperationSettings", + "getBackupSettings", + "listBackupsSettings", + "updateBackupSettings", + "deleteBackupSettings", + "restoreTableSettings", + "restoreTableOperationSettings", + }; + + @Test + public void testToString() throws IOException { + BigtableTableAdminSettings defaultSettings = + BigtableTableAdminSettings.newBuilder() + .setProjectId("our-project-85") + .setInstanceId("our-instance-06") + .build(); + + checkToString(defaultSettings); + + BigtableTableAdminSettings.Builder builder = defaultSettings.toBuilder(); + BigtableTableAdminStubSettings.Builder stubSettings = + builder.stubSettings().setEndpoint("example.com:1234"); + + stubSettings + .getBackupSettings() + .setRetrySettings( + RetrySettings.newBuilder().setTotalTimeout(Duration.ofMinutes(812)).build()); + + BigtableTableAdminSettings settings = builder.build(); + checkToString(settings); + assertThat(defaultSettings.toString()).doesNotContain("endpoint=example.com:1234"); + assertThat(settings.toString()).contains("endpoint=example.com:1234"); + assertThat(defaultSettings.toString()).doesNotContain("totalTimeout=PT13H32M"); + assertThat(settings.toString()).contains("totalTimeout=PT13H32M"); + + int nonStaticFields = 0; + for (Field field : BigtableTableAdminStubSettings.class.getDeclaredFields()) { + if (!Modifier.isStatic(field.getModifiers())) { + nonStaticFields++; + } + } + // failure will signal about adding a new settings property + assertThat(SETTINGS_LIST.length).isEqualTo(nonStaticFields); + } + + void checkToString(BigtableTableAdminSettings settings) { + String projectId = settings.getProjectId(); + String instanceId = settings.getInstanceId(); + String toString = settings.toString(); + assertThat(toString).isEqualTo(settings.toString()); // no variety + assertThat(toString) + .startsWith( + "BigtableTableAdminSettings{projectId=" + projectId + ", instanceId=" + instanceId); + for (String subSettings : SETTINGS_LIST) { + assertThat(toString).contains(subSettings + "="); + } + assertThat(toString.contains(settings.getStubSettings().toString())); + } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableBackupIT.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableBackupIT.java index 4d17bbf0e9..10bd7da14d 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableBackupIT.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableBackupIT.java @@ -15,6 +15,7 @@ */ package com.google.cloud.bigtable.admin.v2.it; +import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static io.grpc.Status.Code.NOT_FOUND; import static org.junit.Assert.fail; @@ -22,6 +23,7 @@ import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.api.gax.rpc.ApiException; +import com.google.cloud.Policy; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; import com.google.cloud.bigtable.admin.v2.models.Backup; @@ -331,6 +333,33 @@ public void restoreTableTest() throws InterruptedException, ExecutionException { } } + @Test + public void backupIamTest() throws InterruptedException { + String backupId = generateId("iam-" + TEST_BACKUP_SUFFIX); + createBackupAndWait(backupId); + + Policy policy = tableAdmin.getBackupIamPolicy(targetCluster, backupId); + assertThat(policy).isNotNull(); + + Exception actualEx = null; + try { + assertThat(tableAdmin.setBackupIamPolicy(targetCluster, backupId, policy)).isNotNull(); + } catch (Exception iamException) { + actualEx = iamException; + } + assertThat(actualEx).isNull(); + + List permissions = + tableAdmin.testBackupIamPermission( + targetCluster, + backupId, + "bigtable.backups.get", + "bigtable.backups.delete", + "bigtable.backups.update", + "bigtable.backups.restore"); + assertThat(permissions).hasSize(4); + } + private CreateBackupRequest createBackupRequest(String backupName) { return CreateBackupRequest.of(targetCluster, backupName) .setSourceTableId(testTable.getId()) diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactoryTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactoryTest.java index c79fd38851..25c341d650 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactoryTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataClientFactoryTest.java @@ -18,22 +18,32 @@ import static com.google.common.truth.Truth.assertThat; import com.google.api.core.ApiClock; +import com.google.api.core.ApiFunction; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.ExecutorProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.api.gax.rpc.WatchdogProvider; import com.google.bigtable.v2.BigtableGrpc; import com.google.bigtable.v2.MutateRowRequest; import com.google.bigtable.v2.MutateRowResponse; +import com.google.bigtable.v2.ReadRowsRequest; +import com.google.bigtable.v2.ReadRowsResponse; +import com.google.bigtable.v2.RowFilter; +import com.google.bigtable.v2.RowSet; import com.google.cloud.bigtable.data.v2.internal.NameUtil; import com.google.cloud.bigtable.data.v2.models.RowMutation; import com.google.common.base.Preconditions; -import io.grpc.Server; -import io.grpc.ServerBuilder; +import com.google.protobuf.ByteString; +import io.grpc.Attributes; +import io.grpc.ServerTransportFilter; import io.grpc.stub.StreamObserver; import java.io.IOException; import java.lang.reflect.Method; -import java.net.ServerSocket; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -54,7 +64,7 @@ public class BigtableDataClientFactoryTest { private static final String DEFAULT_INSTANCE_ID = "fake-instance"; private static final String DEFAULT_APP_PROFILE_ID = "fake-app-profile"; - private Server fakeServer; + private FakeServiceHelper serviceHelper; private FakeBigtableService service; private TransportChannelProvider transportChannelProvider; @@ -63,18 +73,30 @@ public class BigtableDataClientFactoryTest { private WatchdogProvider watchdogProvider; private ApiClock apiClock; private BigtableDataSettings defaultSettings; + private int port; + + private final BlockingQueue setUpAttributes = new LinkedBlockingDeque<>(); + private final BlockingQueue terminateAttributes = new LinkedBlockingDeque<>(); @Before public void setUp() throws IOException { service = new FakeBigtableService(); - - // Create a fake server for the client to connect to - final int port; - try (ServerSocket ss = new ServerSocket(0)) { - port = ss.getLocalPort(); - } - fakeServer = ServerBuilder.forPort(port).addService(service).build(); - fakeServer.start(); + ServerTransportFilter transportFilter = + new ServerTransportFilter() { + @Override + public Attributes transportReady(Attributes transportAttrs) { + setUpAttributes.add(transportAttrs); + return super.transportReady(transportAttrs); + } + + @Override + public void transportTerminated(Attributes transportAttrs) { + terminateAttributes.add(transportAttrs); + } + }; + serviceHelper = new FakeServiceHelper(null, transportFilter, service); + port = serviceHelper.getPort(); + serviceHelper.start(); BigtableDataSettings.Builder builder = BigtableDataSettings.newBuilderForEmulator(port) @@ -122,9 +144,7 @@ public void setUp() throws IOException { @After public void tearDown() { - if (fakeServer != null) { - fakeServer.shutdownNow(); - } + serviceHelper.shutdown(); } @Test @@ -201,8 +221,94 @@ public void testCreateForInstanceWithAppProfileHasCorrectSettings() throws Excep assertThat(service.lastRequest.getAppProfileId()).isEqualTo("other-app-profile"); } + @Test + public void testCreateWithRefreshingChannel() throws Exception { + String[] tableIds = {"fake-table1", "fake-table2"}; + int poolSize = 3; + BigtableDataSettings.Builder builder = + BigtableDataSettings.newBuilderForEmulator(port) + .setProjectId(DEFAULT_PROJECT_ID) + .setInstanceId(DEFAULT_INSTANCE_ID) + .setAppProfileId(DEFAULT_APP_PROFILE_ID) + .setPrimingTableIds(tableIds) + .setRefreshingChannel(true); + builder + .stubSettings() + .setCredentialsProvider(credentialsProvider) + .setStreamWatchdogProvider(watchdogProvider) + .setExecutorProvider(executorProvider); + InstantiatingGrpcChannelProvider channelProvider = + (InstantiatingGrpcChannelProvider) builder.stubSettings().getTransportChannelProvider(); + InstantiatingGrpcChannelProvider.Builder channelProviderBuilder = channelProvider.toBuilder(); + channelProviderBuilder.setPoolSize(poolSize); + builder.stubSettings().setTransportChannelProvider(channelProviderBuilder.build()); + + BigtableDataClientFactory factory = BigtableDataClientFactory.create(builder.build()); + factory.createDefault(); + factory.createForAppProfile("other-appprofile"); + factory.createForInstance("other-project", "other-instance"); + + // Make sure that only 1 instance is created for all clients + Mockito.verify(credentialsProvider, Mockito.times(1)).getCredentials(); + Mockito.verify(executorProvider, Mockito.times(1)).getExecutor(); + Mockito.verify(watchdogProvider, Mockito.times(1)).getWatchdog(); + + // Make sure that the clients are sharing the same ChannelPool + assertThat(setUpAttributes).hasSize(poolSize); + + // Make sure that prime requests were sent only once per table per connection + assertThat(service.readRowsRequests).hasSize(poolSize * tableIds.length); + List expectedRequests = new LinkedList<>(); + for (String tableId : tableIds) { + for (int i = 0; i < poolSize; i++) { + expectedRequests.add( + ReadRowsRequest.newBuilder() + .setTableName( + String.format( + "projects/%s/instances/%s/tables/%s", + DEFAULT_PROJECT_ID, DEFAULT_INSTANCE_ID, tableId)) + .setAppProfileId(DEFAULT_APP_PROFILE_ID) + .setRows( + RowSet.newBuilder() + .addRowKeys(ByteString.copyFromUtf8("nonexistent-priming-row"))) + .setFilter(RowFilter.newBuilder().setBlockAllFilter(true).build()) + .setRowsLimit(1) + .build()); + } + } + assertThat(service.readRowsRequests).containsExactly(expectedRequests.toArray()); + + // Wait for all the connections to close asynchronously + factory.close(); + long sleepTimeMs = 1000; + Thread.sleep(sleepTimeMs); + // Verify that all the channels are closed + assertThat(terminateAttributes).hasSize(poolSize); + } + private static class FakeBigtableService extends BigtableGrpc.BigtableImplBase { + volatile MutateRowRequest lastRequest; + BlockingQueue readRowsRequests = new LinkedBlockingDeque<>(); + private ApiFunction readRowsCallback = + new ApiFunction() { + @Override + public ReadRowsResponse apply(ReadRowsRequest readRowsRequest) { + return ReadRowsResponse.getDefaultInstance(); + } + }; + + @Override + public void readRows( + ReadRowsRequest request, StreamObserver responseObserver) { + try { + readRowsRequests.add(request); + responseObserver.onNext(readRowsCallback.apply(request)); + responseObserver.onCompleted(); + } catch (RuntimeException e) { + responseObserver.onError(e); + } + } @Override public void mutateRow( @@ -214,6 +320,7 @@ public void mutateRow( } private static class BuilderAnswer implements Answer { + private final Class targetClass; private T targetInstance; diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataSettingsTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataSettingsTest.java new file mode 100644 index 0000000000..2053a434f4 --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/BigtableDataSettingsTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020 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 + * + * https://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.google.cloud.bigtable.data.v2; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings; +import org.junit.Test; + +public class BigtableDataSettingsTest { + + @Test + public void testToString() { + BigtableDataSettings settings = + BigtableDataSettings.newBuilder() + .setProjectId("our-project-2-12") + .setInstanceId("our-instance-85") + .setAppProfileId("our-appProfile-06") + .build(); + EnhancedBigtableStubSettings stubSettings = settings.getStubSettings(); + assertThat(settings.toString()) + .isEqualTo("BigtableDataSettings{stubSettings=" + stubSettings.toString() + "}"); + } +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/FakeServiceHelper.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/FakeServiceHelper.java new file mode 100644 index 0000000000..9ec5e59cb7 --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/FakeServiceHelper.java @@ -0,0 +1,72 @@ +/* + * Copyright 2020 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 + * + * https://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.google.cloud.bigtable.data.v2; + +import io.grpc.BindableService; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptor; +import io.grpc.ServerTransportFilter; +import java.io.IOException; +import java.net.ServerSocket; + +/** Utility class to setup a fake grpc server on a random port. */ +public class FakeServiceHelper { + private final int port; + private final Server server; + + public FakeServiceHelper(BindableService... services) throws IOException { + this(null, services); + } + + public FakeServiceHelper(ServerInterceptor interceptor, BindableService... services) + throws IOException { + this(interceptor, null, services); + } + + public FakeServiceHelper( + ServerInterceptor interceptor, + ServerTransportFilter transportFilter, + BindableService... services) + throws IOException { + try (ServerSocket ss = new ServerSocket(0)) { + port = ss.getLocalPort(); + } + ServerBuilder builder = ServerBuilder.forPort(port); + if (interceptor != null) { + builder = builder.intercept(interceptor); + } + if (transportFilter != null) { + builder = builder.addTransportFilter(transportFilter); + } + for (BindableService service : services) { + builder = builder.addService(service); + } + server = builder.build(); + } + + public int getPort() { + return port; + } + + public void start() throws IOException { + server.start(); + } + + public void shutdown() { + server.shutdown(); + } +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimerTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimerTest.java index 42d13a7ab1..3748a5adff 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimerTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/BigtableChannelPrimerTest.java @@ -25,12 +25,11 @@ import com.google.bigtable.v2.ReadRowsResponse; import com.google.bigtable.v2.RowFilter; import com.google.bigtable.v2.RowSet; +import com.google.cloud.bigtable.data.v2.FakeServiceHelper; import com.google.common.collect.ImmutableList; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.Metadata; -import io.grpc.Server; -import io.grpc.ServerBuilder; import io.grpc.ServerCall; import io.grpc.ServerCall.Listener; import io.grpc.ServerCallHandler; @@ -39,7 +38,6 @@ import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.net.ServerSocket; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Handler; @@ -57,28 +55,20 @@ public class BigtableChannelPrimerTest { private static final String TOKEN_VALUE = "fake-token"; - int port; - Server server; FakeService fakeService; MetadataInterceptor metadataInterceptor; BigtableChannelPrimer primer; ManagedChannel channel; private LogHandler logHandler; + private FakeServiceHelper serviceHelper; @Before public void setup() throws IOException { - try (ServerSocket ss = new ServerSocket(0)) { - port = ss.getLocalPort(); - } catch (IOException e) { - e.printStackTrace(); - } - fakeService = new FakeService(); metadataInterceptor = new MetadataInterceptor(); - server = - ServerBuilder.forPort(port).intercept(metadataInterceptor).addService(fakeService).build(); - server.start(); + serviceHelper = new FakeServiceHelper(metadataInterceptor, fakeService); + serviceHelper.start(); primer = BigtableChannelPrimer.create( OAuth2Credentials.create(new AccessToken(TOKEN_VALUE, null)), @@ -87,8 +77,10 @@ public void setup() throws IOException { "fake-app-profile", ImmutableList.of("table1", "table2")); - channel = ManagedChannelBuilder.forAddress("localhost", port).usePlaintext().build(); - + channel = + ManagedChannelBuilder.forAddress("localhost", serviceHelper.getPort()) + .usePlaintext() + .build(); logHandler = new LogHandler(); Logger.getLogger(BigtableChannelPrimer.class.toString()).addHandler(logHandler); } @@ -97,7 +89,7 @@ public void setup() throws IOException { public void teardown() { Logger.getLogger(BigtableChannelPrimer.class.toString()).removeHandler(logHandler); channel.shutdown(); - server.shutdown(); + serviceHelper.shutdown(); } @Test diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettingsTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettingsTest.java index 9a3eb874d1..2cd55a311c 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettingsTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettingsTest.java @@ -19,20 +19,29 @@ import com.google.api.gax.batching.BatchingSettings; import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.ServerStreamingCallSettings; import com.google.api.gax.rpc.StatusCode.Code; import com.google.api.gax.rpc.UnaryCallSettings; import com.google.api.gax.rpc.WatchdogProvider; +import com.google.auth.Credentials; import com.google.cloud.bigtable.data.v2.models.ConditionalRowMutation; import com.google.cloud.bigtable.data.v2.models.KeyOffset; import com.google.cloud.bigtable.data.v2.models.Query; import com.google.cloud.bigtable.data.v2.models.Row; import com.google.cloud.bigtable.data.v2.models.RowMutation; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Range; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,7 +70,7 @@ public void settingsAreNotLostTest() { String projectId = "my-project"; String instanceId = "my-instance"; String appProfileId = "my-app-profile-id"; - boolean isRefreshingChannel = true; + boolean isRefreshingChannel = false; String endpoint = "some.other.host:123"; CredentialsProvider credentialsProvider = Mockito.mock(CredentialsProvider.class); WatchdogProvider watchdogProvider = Mockito.mock(WatchdogProvider.class); @@ -612,4 +621,127 @@ public void isRefreshingChannelFalseValueTest() { assertThat(builder.build().isRefreshingChannel()).isFalse(); assertThat(builder.build().toBuilder().isRefreshingChannel()).isFalse(); } + + static final String[] SETTINGS_LIST = { + "projectId", + "instanceId", + "appProfileId", + "isRefreshingChannel", + "primedTableIds", + "readRowsSettings", + "readRowSettings", + "sampleRowKeysSettings", + "mutateRowSettings", + "bulkMutateRowsSettings", + "bulkReadRowsSettings", + "checkAndMutateRowSettings", + "readModifyWriteRowSettings", + }; + + @Test + public void testToString() { + EnhancedBigtableStubSettings defaultSettings = + EnhancedBigtableStubSettings.newBuilder() + .setProjectId("our-project-85") + .setInstanceId("our-instance-06") + .setAppProfileId("our-appProfile-06") + .build(); + + checkToString(defaultSettings); + assertThat(defaultSettings.toString()).contains("primedTableIds=[]"); + + EnhancedBigtableStubSettings settings = + defaultSettings + .toBuilder() + .setPrimedTableIds("2", "12", "85", "06") + .setEndpoint("example.com:1234") + .build(); + + checkToString(settings); + assertThat(settings.toString()).contains("endpoint=example.com:1234"); + assertThat(settings.toString()).contains("primedTableIds=[2, 12, 85, 06]"); + + int nonStaticFields = 0; + for (Field field : EnhancedBigtableStubSettings.class.getDeclaredFields()) { + if (!Modifier.isStatic(field.getModifiers())) { + nonStaticFields++; + } + } + // failure will signal about adding a new settings property + assertThat(SETTINGS_LIST.length).isEqualTo(nonStaticFields); + } + + void checkToString(EnhancedBigtableStubSettings settings) { + String projectId = settings.getProjectId(); + String instanceId = settings.getInstanceId(); + String appProfileId = settings.getAppProfileId(); + String isRefreshingChannel = "" + settings.isRefreshingChannel(); + String toString = settings.toString(); + assertThat(toString).isEqualTo(settings.toString()); // no variety + assertThat(toString) + .startsWith( + "EnhancedBigtableStubSettings{projectId=" + + projectId + + ", instanceId=" + + instanceId + + ", appProfileId=" + + appProfileId + + ", isRefreshingChannel=" + + isRefreshingChannel); + for (String subSettings : SETTINGS_LIST) { + assertThat(toString).contains(subSettings + "="); + } + } + + @Test + public void refreshingChannelSetFixedCredentialProvider() throws Exception { + String dummyProjectId = "my-project"; + String dummyInstanceId = "my-instance"; + CredentialsProvider credentialsProvider = Mockito.mock(CredentialsProvider.class); + FakeCredentials expectedCredentials = new FakeCredentials(); + Mockito.when(credentialsProvider.getCredentials()) + .thenReturn(expectedCredentials, new FakeCredentials(), new FakeCredentials()); + EnhancedBigtableStubSettings.Builder builder = + EnhancedBigtableStubSettings.newBuilder() + .setProjectId(dummyProjectId) + .setInstanceId(dummyInstanceId) + .setRefreshingChannel(true) + .setCredentialsProvider(credentialsProvider); + assertThat(builder.isRefreshingChannel()).isTrue(); + // Verify that isRefreshing setting is not lost and stubSettings will always return the same + // credential + EnhancedBigtableStubSettings stubSettings = builder.build(); + assertThat(stubSettings.isRefreshingChannel()).isTrue(); + assertThat(stubSettings.getCredentialsProvider()).isInstanceOf(FixedCredentialsProvider.class); + assertThat(stubSettings.getCredentialsProvider().getCredentials()) + .isEqualTo(expectedCredentials); + assertThat(stubSettings.toBuilder().isRefreshingChannel()).isTrue(); + assertThat(stubSettings.toBuilder().getCredentialsProvider().getCredentials()) + .isEqualTo(expectedCredentials); + } + + private static class FakeCredentials extends Credentials { + @Override + public String getAuthenticationType() { + return "fake"; + } + + @Override + public Map> getRequestMetadata(URI uri) throws IOException { + return ImmutableMap.of("my-header", Arrays.asList("fake-credential")); + } + + @Override + public boolean hasRequestMetadata() { + return true; + } + + @Override + public boolean hasRequestMetadataOnly() { + return true; + } + + @Override + public void refresh() throws IOException {} + } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubTest.java index b9c5c96167..194123b1bd 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubTest.java @@ -25,6 +25,7 @@ import com.google.bigtable.v2.RowSet; import com.google.cloud.bigtable.admin.v2.internal.NameUtil; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.FakeServiceHelper; import com.google.cloud.bigtable.data.v2.internal.RequestContext; import com.google.cloud.bigtable.data.v2.models.DefaultRowAdapter; import com.google.cloud.bigtable.data.v2.models.Query; @@ -34,15 +35,12 @@ import com.google.protobuf.BytesValue; import com.google.protobuf.StringValue; import io.grpc.Metadata; -import io.grpc.Server; -import io.grpc.ServerBuilder; import io.grpc.ServerCall; import io.grpc.ServerCall.Listener; import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.net.ServerSocket; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import org.junit.After; @@ -60,7 +58,7 @@ public class EnhancedBigtableStubTest { NameUtil.formatTableName(PROJECT_ID, INSTANCE_ID, "fake-table"); private static final String APP_PROFILE_ID = "app-profile-id"; - private Server server; + FakeServiceHelper serviceHelper; private MetadataInterceptor metadataInterceptor; private FakeDataService fakeDataService; private EnhancedBigtableStubSettings defaultSettings; @@ -68,21 +66,13 @@ public class EnhancedBigtableStubTest { @Before public void setUp() throws IOException, IllegalAccessException, InstantiationException { - int port; - try (ServerSocket ss = new ServerSocket(0)) { - port = ss.getLocalPort(); - } metadataInterceptor = new MetadataInterceptor(); fakeDataService = new FakeDataService(); - server = - ServerBuilder.forPort(port) - .intercept(metadataInterceptor) - .addService(fakeDataService) - .build(); - server.start(); + serviceHelper = new FakeServiceHelper(metadataInterceptor, fakeDataService); + serviceHelper.start(); defaultSettings = - BigtableDataSettings.newBuilderForEmulator(port) + BigtableDataSettings.newBuilderForEmulator(serviceHelper.getPort()) .setProjectId(PROJECT_ID) .setInstanceId(INSTANCE_ID) .setAppProfileId(APP_PROFILE_ID) @@ -95,7 +85,7 @@ public void setUp() throws IOException, IllegalAccessException, InstantiationExc @After public void tearDown() { - server.shutdown(); + serviceHelper.shutdown(); } @Test @@ -159,7 +149,7 @@ public void testUserAgent() throws InterruptedException { assertThat(metadataInterceptor.headers).hasSize(1); Metadata metadata = metadataInterceptor.headers.take(); assertThat(metadata.get(Metadata.Key.of("user-agent", Metadata.ASCII_STRING_MARSHALLER))) - .contains("bigtable-java/"); + .containsMatch("bigtable-java/\\d+\\.\\d+\\.\\d+(?:-SNAPSHOT)?"); } private static class MetadataInterceptor implements ServerInterceptor { diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/HeadersTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/HeadersTest.java index c6c5740d8d..760dd19911 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/HeadersTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/HeadersTest.java @@ -35,18 +35,16 @@ import com.google.bigtable.v2.SampleRowKeysResponse; import com.google.cloud.bigtable.data.v2.BigtableDataClient; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.FakeServiceHelper; import com.google.cloud.bigtable.data.v2.internal.NameUtil; import com.google.cloud.bigtable.data.v2.models.*; import com.google.cloud.bigtable.data.v2.models.Mutation; import com.google.rpc.Status; import io.grpc.Metadata; -import io.grpc.Server; -import io.grpc.ServerBuilder; import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; -import java.net.ServerSocket; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import org.junit.After; @@ -72,26 +70,18 @@ public class HeadersTest { private static final Metadata.Key TEST_FIXED_HEADER = Metadata.Key.of(TEST_FIXED_HEADER_STRING, Metadata.ASCII_STRING_MARSHALLER); - private Server server; + FakeServiceHelper serviceHelper; private BlockingQueue sentMetadata = new ArrayBlockingQueue<>(10); private BigtableDataClient client; @Before public void setUp() throws Exception { - int port; - try (ServerSocket ss = new ServerSocket(0)) { - port = ss.getLocalPort(); - } - server = - ServerBuilder.forPort(port) - .addService(new FakeBigtableService()) - .intercept(new MetadataInterceptor()) - .build(); - server.start(); + serviceHelper = new FakeServiceHelper(new MetadataInterceptor(), new FakeBigtableService()); + serviceHelper.start(); BigtableDataSettings.Builder settings = - BigtableDataSettings.newBuilderForEmulator(port) + BigtableDataSettings.newBuilderForEmulator(serviceHelper.getPort()) .setProjectId(PROJECT_ID) .setInstanceId(INSTANCE_ID) .setAppProfileId(APP_PROFILE_ID); @@ -119,7 +109,7 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { client.close(); - server.shutdown(); + serviceHelper.shutdown(); } @Test diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java index 49ebae81f2..4b025303e4 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java @@ -25,6 +25,7 @@ import com.google.bigtable.v2.ReadRowsResponse; import com.google.bigtable.v2.ReadRowsResponse.CellChunk; import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.FakeServiceHelper; import com.google.cloud.bigtable.data.v2.models.Query; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub; import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings; @@ -35,8 +36,6 @@ import com.google.protobuf.ByteString; import com.google.protobuf.BytesValue; import com.google.protobuf.StringValue; -import io.grpc.Server; -import io.grpc.ServerBuilder; import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; @@ -54,7 +53,6 @@ import io.opencensus.tags.TagKey; import io.opencensus.tags.TagValue; import io.opencensus.tags.Tags; -import java.net.ServerSocket; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -95,7 +93,7 @@ public class MetricsTracerTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - private Server server; + FakeServiceHelper serviceHelper; @Mock(answer = Answers.CALLS_REAL_METHODS) private BigtableGrpc.BigtableImplBase mockService; @@ -105,17 +103,13 @@ public class MetricsTracerTest { @Before public void setUp() throws Exception { - int port; - try (ServerSocket ss = new ServerSocket(0)) { - port = ss.getLocalPort(); - } - server = ServerBuilder.forPort(port).addService(mockService).build(); - server.start(); + serviceHelper = new FakeServiceHelper(mockService); + serviceHelper.start(); RpcViews.registerBigtableClientViews(localStats.getViewManager()); BigtableDataSettings settings = - BigtableDataSettings.newBuilderForEmulator(port) + BigtableDataSettings.newBuilderForEmulator(serviceHelper.getPort()) .setProjectId(PROJECT_ID) .setInstanceId(INSTANCE_ID) .setAppProfileId(APP_PROFILE_ID) @@ -130,7 +124,7 @@ public void setUp() throws Exception { @After public void tearDown() { stub.close(); - server.shutdown(); + serviceHelper.shutdown(); } @Test diff --git a/grpc-google-cloud-bigtable-admin-v2/pom.xml b/grpc-google-cloud-bigtable-admin-v2/pom.xml index ca1e1c2d4c..5cce7bb67c 100644 --- a/grpc-google-cloud-bigtable-admin-v2/pom.xml +++ b/grpc-google-cloud-bigtable-admin-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-bigtable-admin-v2 - 1.16.2 + 1.17.0 grpc-google-cloud-bigtable-admin-v2 GRPC library for grpc-google-cloud-bigtable-admin-v2 com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 @@ -18,14 +18,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import diff --git a/grpc-google-cloud-bigtable-v2/pom.xml b/grpc-google-cloud-bigtable-v2/pom.xml index 2aac8550e4..e4327b02de 100644 --- a/grpc-google-cloud-bigtable-v2/pom.xml +++ b/grpc-google-cloud-bigtable-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-bigtable-v2 - 1.16.2 + 1.17.0 grpc-google-cloud-bigtable-v2 GRPC library for grpc-google-cloud-bigtable-v2 com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 @@ -18,14 +18,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import diff --git a/pom.xml b/pom.xml index 3fa06a7b70..c3578b4ee4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ google-cloud-bigtable-parent pom - 1.16.2 + 1.17.0 Google Cloud Bigtable Parent https://github.com/googleapis/java-bigtable @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.9.2 + 0.9.3 @@ -181,7 +181,7 @@ com.google.truth truth - 1.0.1 + 1.1 junit diff --git a/proto-google-cloud-bigtable-admin-v2/pom.xml b/proto-google-cloud-bigtable-admin-v2/pom.xml index 27bdecaf8d..c99a04c668 100644 --- a/proto-google-cloud-bigtable-admin-v2/pom.xml +++ b/proto-google-cloud-bigtable-admin-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-bigtable-admin-v2 - 1.16.2 + 1.17.0 proto-google-cloud-bigtable-admin-v2 PROTO library for proto-google-cloud-bigtable-admin-v2 com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 @@ -18,14 +18,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import diff --git a/proto-google-cloud-bigtable-v2/pom.xml b/proto-google-cloud-bigtable-v2/pom.xml index 372427e419..dfd225c814 100644 --- a/proto-google-cloud-bigtable-v2/pom.xml +++ b/proto-google-cloud-bigtable-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-bigtable-v2 - 1.16.2 + 1.17.0 proto-google-cloud-bigtable-v2 PROTO library for proto-google-cloud-bigtable-v2 com.google.cloud google-cloud-bigtable-parent - 1.16.2 + 1.17.0 @@ -18,14 +18,14 @@ com.google.cloud google-cloud-bigtable-deps-bom - 1.16.2 + 1.17.0 pom import com.google.cloud google-cloud-bigtable-bom - 1.16.2 + 1.17.0 pom import diff --git a/renovate.json b/renovate.json index a1cf364338..9022e7bfc4 100644 --- a/renovate.json +++ b/renovate.json @@ -17,24 +17,6 @@ ], "versionScheme": "docker" }, - { - "packagePatterns": [ - "^com.google.api:gax", - "^com.google.auth:", - "^com.google.cloud:google-cloud-core", - "^io.grpc:", - "^com.google.guava:" - ], - "groupName": "core dependencies" - }, - { - "packagePatterns": [ - "^com.google.http-client:", - "^com.google.oauth-client:", - "^com.google.api-client:" - ], - "groupName": "core transport dependencies" - }, { "packagePatterns": [ "*" @@ -63,6 +45,16 @@ "semanticCommitType": "chore", "semanticCommitScope": "deps" }, + { + "packagePatterns": [ + "^junit:junit", + "^com.google.truth:truth", + "^org.mockito:mockito-core", + "^org.objenesis:objenesis" + ], + "semanticCommitType": "test", + "semanticCommitScope": "deps" + }, { "packagePatterns": [ "^com.google.cloud:google-cloud-" @@ -78,4 +70,4 @@ ], "semanticCommits": true, "masterIssue": true -} \ No newline at end of file +} diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 85b2196297..f84fef947d 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-bigtable - 1.16.1 + 1.16.2 @@ -42,7 +42,7 @@ com.google.truth truth - 1.0.1 + 1.1 test diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index d0c65596d7..4540352641 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-bigtable - 1.16.2 + 1.17.0 @@ -41,7 +41,7 @@ com.google.truth truth - 1.0.1 + 1.1 test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index a7b2c71c48..c2733f4f19 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 12.1.0 + 13.2.0 pom import @@ -53,7 +53,7 @@ com.google.truth truth - 1.0.1 + 1.1 test diff --git a/samples/snippets/src/main/java/com/m/examples/bigtable/Quickstart.java b/samples/snippets/src/main/java/com/m/examples/bigtable/Quickstart.java index 7ca481f1bd..6bdfa70135 100644 --- a/samples/snippets/src/main/java/com/m/examples/bigtable/Quickstart.java +++ b/samples/snippets/src/main/java/com/m/examples/bigtable/Quickstart.java @@ -26,11 +26,15 @@ public class Quickstart { - public static void quickstart(String projectId, String instanceId, String tableId) { - // String projectId = "my-project-id"; - // String instanceId = "my-instance-id"; - // String tableId = "my-table-id"; + public static void main(String... args) { + String projectId = args[0]; // my-gcp-project-id + String instanceId = args[1]; // my-bigtable-instance-id + String tableId = args[2]; // my-bigtable-table-id + + quickstart(projectId, instanceId, tableId); + } + public static void quickstart(String projectId, String instanceId, String tableId) { BigtableDataSettings settings = BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId).build(); diff --git a/synth.metadata b/synth.metadata index be30a94c13..38ca1902a1 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-bigtable.git", - "sha": "1fa6f62ee17fbd317cf18e68aae5dedabf2b21e3" + "sha": "2851141b7c3b345167ce1cd1db0dab3084bc2779" } }, { @@ -19,7 +19,7 @@ "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "b65ef07d99946d23e900ef2cc490274a16edd336" + "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" } } ], @@ -50,7 +50,9 @@ ".github/PULL_REQUEST_TEMPLATE.md", ".github/readme/synth.py", ".github/release-please.yml", + ".github/snippet-bot.yml", ".github/trusted-contribution.yml", + ".github/workflows/approve-readme.yaml", ".github/workflows/auto-release.yaml", ".github/workflows/ci.yaml", ".github/workflows/formatting.yaml", diff --git a/versions.txt b/versions.txt index 5967c1b459..719a2daeb6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,9 +1,9 @@ # Format: # module:released-version:current-version -google-cloud-bigtable:1.16.2:1.16.2 -grpc-google-cloud-bigtable-admin-v2:1.16.2:1.16.2 -grpc-google-cloud-bigtable-v2:1.16.2:1.16.2 -proto-google-cloud-bigtable-admin-v2:1.16.2:1.16.2 -proto-google-cloud-bigtable-v2:1.16.2:1.16.2 -google-cloud-bigtable-emulator:0.125.2:0.125.2 +google-cloud-bigtable:1.17.0:1.17.0 +grpc-google-cloud-bigtable-admin-v2:1.17.0:1.17.0 +grpc-google-cloud-bigtable-v2:1.17.0:1.17.0 +proto-google-cloud-bigtable-admin-v2:1.17.0:1.17.0 +proto-google-cloud-bigtable-v2:1.17.0:1.17.0 +google-cloud-bigtable-emulator:0.126.0:0.126.0