diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 3473042c08..f60d774937 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:df8d7b2cc0dbc65871e7edd86601901a0612b272fa3f7f0eb590c5c53aa5f92e + digest: sha256:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813 +# created: 2022-04-06T16:30:03.627422514Z diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml new file mode 100644 index 0000000000..4caef688b7 --- /dev/null +++ b/.github/auto-label.yaml @@ -0,0 +1,15 @@ +# Copyright 2021 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. +requestsize: + enabled: true diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 47afe3b4e7..5de852eebe 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -91,6 +91,20 @@ branchProtectionRules: - units (11) - 'Kokoro - Test: Integration' - cla/google + - pattern: feat/grpc-storage + isAdminEnforced: true + requiredApprovingReviewCount: 1 + requiresCodeOwnerReviews: true + requiresStrictStatusChecks: false + requiredStatusCheckContexts: + - dependencies (8) + - dependencies (11) + - lint + - clirr + - units (8) + - units (11) + - 'Kokoro - Test: Integration' + - cla/google permissionRules: - team: yoshi-admins permission: admin diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg index 4c7225ec92..c0d2e84254 100644 --- a/.kokoro/presubmit/graalvm-native.cfg +++ b/.kokoro/presubmit/graalvm-native.cfg @@ -31,3 +31,8 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + +env_vars: { + key: "IT_SERVICE_ACCOUNT_EMAIL" + value: "it-service-account@gcloud-devel.iam.gserviceaccount.com" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e92957846..15d0a2cfc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +### [2.6.1](https://github.com/googleapis/java-storage/compare/v2.6.0...v2.6.1) (2022-04-15) + + +### Bug Fixes + +* add gccl-invocation-id interceptor ([#1309](https://github.com/googleapis/java-storage/issues/1309)) ([335c267](https://github.com/googleapis/java-storage/commit/335c2679b70f0bcd4db895d9cb4cbe97175e8070)) +* **java:** add service account email to Native Image testing kokoro job ([#1348](https://github.com/googleapis/java-storage/issues/1348)) ([9f76fcc](https://github.com/googleapis/java-storage/commit/9f76fccfddcc0d3a671ec4281dab303da07b9959)) + + +### Documentation + +* Adding PubSub Notification Samples ([#1317](https://github.com/googleapis/java-storage/issues/1317)) ([fa9920d](https://github.com/googleapis/java-storage/commit/fa9920d9097cfe6863c3e733a091c9b867d603ef)) +* Adding Samples for Creating Dual Region Buckets ([#1341](https://github.com/googleapis/java-storage/issues/1341)) ([9396061](https://github.com/googleapis/java-storage/commit/9396061ac71f98efd6784c34da3bbea04f48873d)) +* Update CreateBucketPubSubNotification to have line without horizontal scrolling ([#1335](https://github.com/googleapis/java-storage/issues/1335)) ([09b7842](https://github.com/googleapis/java-storage/commit/09b78424f7090c7c0469709a357a06143668e31b)) + + +### Dependencies + +* update dependency com.google.apis:google-api-services-storage to v1-rev20220401-1.32.1 ([#1337](https://github.com/googleapis/java-storage/issues/1337)) ([a5050e2](https://github.com/googleapis/java-storage/commit/a5050e230a620ba727a93c0a93f0bf82a011ce99)) +* update dependency com.google.cloud:google-cloud-pubsub to v1.116.3 ([#1327](https://github.com/googleapis/java-storage/issues/1327)) ([9d8c520](https://github.com/googleapis/java-storage/commit/9d8c520acca7f56f5af46348bc1db71bda1f93aa)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#1352](https://github.com/googleapis/java-storage/issues/1352)) ([ab46f98](https://github.com/googleapis/java-storage/commit/ab46f985768c1539babf4c14a7e030083776ce0e)) +* update dependency com.google.cloud:native-image-support to v0.12.11 ([#1319](https://github.com/googleapis/java-storage/issues/1319)) ([c338c54](https://github.com/googleapis/java-storage/commit/c338c54210940dbe3b97aa0e7b13904e72ede91d)) +* update dependency com.google.cloud:native-image-support to v0.13.1 ([#1353](https://github.com/googleapis/java-storage/issues/1353)) ([0f76d27](https://github.com/googleapis/java-storage/commit/0f76d2773bc159b1c8a9eeddb54ae8406da86e7a)) +* update kms.version to v0.95.2 ([#1331](https://github.com/googleapis/java-storage/issues/1331)) ([2ca4883](https://github.com/googleapis/java-storage/commit/2ca488362ce2cb2b620ed6dc846d76b095d44a31)) +* update kms.version to v0.95.3 ([#1346](https://github.com/googleapis/java-storage/issues/1346)) ([a4f9503](https://github.com/googleapis/java-storage/commit/a4f95038e56ac36badf68edd072705621fec1dbe)) + ## [2.6.0](https://github.com/googleapis/java-storage/compare/v2.5.1...v2.6.0) (2022-03-30) diff --git a/README.md b/README.md index 5f38caabf1..f6208c767b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file com.google.cloud libraries-bom - 25.0.0 + 25.1.0 pom import @@ -41,7 +41,7 @@ If you are using Maven without BOM, add this to your dependencies: com.google.cloud google-cloud-storage - 2.5.1 + 2.6.0 ``` @@ -49,20 +49,20 @@ If you are using Maven without BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies ```Groovy -implementation platform('com.google.cloud:libraries-bom:25.0.0') +implementation platform('com.google.cloud:libraries-bom:25.1.0') implementation 'com.google.cloud:google-cloud-storage' ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-storage:2.5.1' +implementation 'com.google.cloud:google-cloud-storage:2.6.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.5.1" +libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.6.0" ``` ## Authentication @@ -240,9 +240,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/ | Change Default Storage Class | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ChangeDefaultStorageClass.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ChangeDefaultStorageClass.java) | | Configure Bucket Cors | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ConfigureBucketCors.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ConfigureBucketCors.java) | | Create Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) | +| Create Bucket Dual Region | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) | +| Create Bucket Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) | | Create Bucket With Storage Class And Location | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) | | Create Bucket With Turbo Replication | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) | | Delete Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) | +| Delete Bucket Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java) | | Disable Bucket Versioning | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableBucketVersioning.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableBucketVersioning.java) | | Disable Default Event Based Hold | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableDefaultEventBasedHold.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableDefaultEventBasedHold.java) | | Disable Lifecycle Management | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableLifecycleManagement.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableLifecycleManagement.java) | @@ -262,10 +265,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/ | Get Uniform Bucket Level Access | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/GetUniformBucketLevelAccess.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/GetUniformBucketLevelAccess.java) | | List Bucket Iam Members | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListBucketIamMembers.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListBucketIamMembers.java) | | List Buckets | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListBuckets.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListBuckets.java) | +| List Pub Sub Notifications | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java) | | Lock Retention Policy | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/LockRetentionPolicy.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/LockRetentionPolicy.java) | | Make Bucket Public | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/MakeBucketPublic.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/MakeBucketPublic.java) | | Print Bucket Acl | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAcl.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAcl.java) | | Print Bucket Acl Filter By User | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAclFilterByUser.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAclFilterByUser.java) | +| Print Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java) | | Remove Bucket Cors | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketCors.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketCors.java) | | Remove Bucket Default Kms Key | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultKmsKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultKmsKey.java) | | Remove Bucket Default Owner | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultOwner.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultOwner.java) | diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml index 643306e684..9a9d79f9a2 100644 --- a/gapic-google-cloud-storage-v2/pom.xml +++ b/gapic-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha gapic-google-cloud-storage-v2 GRPC library for gapic-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.6.0 + 2.6.1 diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java index 7844e020f0..093223d5ac 100644 --- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java +++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java @@ -891,6 +891,7 @@ public final Policy setIamPolicy(String resource, Policy policy) { * CryptoKeyName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]", "[CRYPTO_KEY]") * .toString()) * .setPolicy(Policy.newBuilder().build()) + * .setUpdateMask(FieldMask.newBuilder().build()) * .build(); * Policy response = storageClient.setIamPolicy(request); * } @@ -917,6 +918,7 @@ public final Policy setIamPolicy(SetIamPolicyRequest request) { * CryptoKeyName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]", "[CRYPTO_KEY]") * .toString()) * .setPolicy(Policy.newBuilder().build()) + * .setUpdateMask(FieldMask.newBuilder().build()) * .build(); * ApiFuture future = storageClient.setIamPolicyCallable().futureCall(request); * // Do something. diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java index 2fc3b0b438..eeff896f37 100644 --- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java +++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java @@ -35,6 +35,7 @@ import com.google.api.gax.rpc.StatusCode; import com.google.api.resourcenames.ResourceName; import com.google.common.collect.Lists; +import com.google.iam.v1.AuditConfig; import com.google.iam.v1.Binding; import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.Policy; @@ -654,6 +655,7 @@ public void getIamPolicyTest() throws Exception { Policy.newBuilder() .setVersion(351608024) .addAllBindings(new ArrayList()) + .addAllAuditConfigs(new ArrayList()) .setEtag(ByteString.EMPTY) .build(); mockStorage.addResponse(expectedResponse); @@ -696,6 +698,7 @@ public void getIamPolicyTest2() throws Exception { Policy.newBuilder() .setVersion(351608024) .addAllBindings(new ArrayList()) + .addAllAuditConfigs(new ArrayList()) .setEtag(ByteString.EMPTY) .build(); mockStorage.addResponse(expectedResponse); @@ -736,6 +739,7 @@ public void setIamPolicyTest() throws Exception { Policy.newBuilder() .setVersion(351608024) .addAllBindings(new ArrayList()) + .addAllAuditConfigs(new ArrayList()) .setEtag(ByteString.EMPTY) .build(); mockStorage.addResponse(expectedResponse); @@ -781,6 +785,7 @@ public void setIamPolicyTest2() throws Exception { Policy.newBuilder() .setVersion(351608024) .addAllBindings(new ArrayList()) + .addAllAuditConfigs(new ArrayList()) .setEtag(ByteString.EMPTY) .build(); mockStorage.addResponse(expectedResponse); diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 8374be3fc9..84fba3dc32 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -1,39 +1,4 @@ - - com/google/cloud/storage/BucketInfo$Builder - com.google.cloud.storage.BucketInfo$Builder setRpo(com.google.cloud.storage.Rpo) - 7013 - - - com/google/cloud/storage/BucketInfo$LifecycleRule$LifecycleAction - BucketInfo$LifecycleRule$LifecycleAction() - 7004 - - - com/google/cloud/storage/Storage - *.Notification createNotification(*.String, *.NotificationInfo) - 7012 - - - com/google/cloud/storage/Storage - *.Notification getNotification(*.String, *.String) - 7012 - - - com/google/cloud/storage/Storage - java.util.List listNotifications(*.String) - 7012 - - - com/google/cloud/storage/Storage - boolean deleteNotification(*.String, *.String) - 7012 - - - com/google/cloud/storage/spi/v1/StorageRpc - *.model.Notification getNotification(*.String, *.String) - 7012 - diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index ffb2bff960..1c2f4df351 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-storage - 2.6.0 + 2.6.1 jar Google Cloud Storage https://github.com/googleapis/java-storage @@ -12,11 +12,11 @@ com.google.cloud google-cloud-storage-parent - 2.6.0 + 2.6.1 google-cloud-storage - 0.95.1 + 0.95.3 @@ -92,6 +92,10 @@ com.fasterxml.jackson.core jackson-core + + com.google.code.findbugs + jsr305 + diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 5e06b6ce24..e03110ff2c 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -1224,7 +1224,7 @@ public abstract static class Builder { /** * Sets the bucket's location. Data for blobs in the bucket resides in physical storage within - * this region. A list of supported values is available here. */ public abstract Builder setLocation(String location); @@ -1731,7 +1731,7 @@ public Long getMetageneration() { /** * Returns the bucket's location. Data for blobs in the bucket resides in physical storage within - * this region. + * this region or regions. * * @see Bucket Locations */ diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java index 3daf2c17ec..51ce17bf3f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java @@ -22,6 +22,7 @@ import com.google.api.gax.retrying.ResultRetryAlgorithm; import com.google.api.gax.retrying.RetrySettings; import com.google.cloud.RetryHelper.RetryHelperException; +import com.google.cloud.storage.spi.v1.HttpRpcContext; import java.util.concurrent.Callable; import java.util.function.Function; @@ -47,11 +48,15 @@ final class Retrying { */ static U run( StorageOptions options, ResultRetryAlgorithm algorithm, Callable c, Function f) { + HttpRpcContext httpRpcContext = HttpRpcContext.getInstance(); try { + httpRpcContext.newInvocationId(); T result = runWithRetries(c, options.getRetrySettings(), algorithm, options.getClock()); return result == null ? null : f.apply(result); } catch (RetryHelperException e) { throw StorageException.coalesce(e); + } finally { + httpRpcContext.clearInvocationId(); } } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java index f3de842fbd..d2bfa27607 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java @@ -38,8 +38,9 @@ public class StorageOptions extends ServiceOptions { private static final String GCS_SCOPE = "https://www.googleapis.com/auth/devstorage.full_control"; private static final Set SCOPES = ImmutableSet.of(GCS_SCOPE); private static final String DEFAULT_HOST = "https://storage.googleapis.com"; - + private static final boolean DEFAULT_INCLUDE_INVOCATION_ID = true; private final RetryAlgorithmManager retryAlgorithmManager; + private final boolean includeInvocationId; public static class DefaultStorageFactory implements StorageFactory { @@ -64,11 +65,13 @@ public ServiceRpc create(StorageOptions options) { public static class Builder extends ServiceOptions.Builder { private StorageRetryStrategy storageRetryStrategy; + private boolean includeInvocationId; private Builder() {} private Builder(StorageOptions options) { super(options); + this.includeInvocationId = options.includeInvocationId; } @Override @@ -93,6 +96,17 @@ public Builder setStorageRetryStrategy(StorageRetryStrategy storageRetryStrategy return this; } + /** + * Override default enablement of invocation id added to x-goog-api-client header. + * + * @param includeInvocationId a boolean to change enablement of invocation id + * @return the builder + */ + Builder setIncludeInvocationId(boolean includeInvocationId) { + this.includeInvocationId = includeInvocationId; + return this; + } + @Override public StorageOptions build() { return new StorageOptions(this, new StorageDefaults()); @@ -105,6 +119,7 @@ private StorageOptions(Builder builder, StorageDefaults serviceDefaults) { new RetryAlgorithmManager( MoreObjects.firstNonNull( builder.storageRetryStrategy, serviceDefaults.getStorageRetryStrategy())); + this.includeInvocationId = builder.includeInvocationId; } private static class StorageDefaults implements ServiceDefaults { @@ -127,6 +142,10 @@ public TransportOptions getDefaultTransportOptions() { public StorageRetryStrategy getStorageRetryStrategy() { return StorageRetryStrategy.getDefaultStorageRetryStrategy(); } + + boolean isIncludeInvocationId() { + return DEFAULT_INCLUDE_INVOCATION_ID; + } } public static HttpTransportOptions getDefaultHttpTransportOptions() { @@ -153,6 +172,11 @@ RetryAlgorithmManager getRetryAlgorithmManager() { return retryAlgorithmManager; } + /** Returns if Invocation ID is enabled and transmitted through x-goog-api-client header. */ + boolean isIncludeInvocationId() { + return includeInvocationId; + } + /** Returns a default {@code StorageOptions} instance. */ public static StorageOptions getDefaultInstance() { return newBuilder().build(); @@ -180,6 +204,8 @@ public boolean equals(Object obj) { } public static Builder newBuilder() { - return new Builder().setHost(DEFAULT_HOST); + return new Builder() + .setHost(DEFAULT_HOST) + .setIncludeInvocationId(DEFAULT_INCLUDE_INVOCATION_ID); } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java new file mode 100644 index 0000000000..a62e7f99d4 --- /dev/null +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java @@ -0,0 +1,72 @@ +/* + * Copyright 2022 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.google.cloud.storage.spi.v1; + +import com.google.api.core.InternalApi; +import java.util.UUID; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +@InternalApi +public final class HttpRpcContext { + + private static final Object GET_INSTANCE_LOCK = new Object(); + + private static volatile HttpRpcContext instance; + + private final ThreadLocal invocationId; + private final Supplier supplier; + + HttpRpcContext(Supplier randomUUID) { + this.invocationId = new InheritableThreadLocal<>(); + this.supplier = randomUUID; + } + + @InternalApi + @Nullable + public UUID getInvocationId() { + return invocationId.get(); + } + + @InternalApi + public UUID newInvocationId() { + invocationId.set(supplier.get()); + return getInvocationId(); + } + + @InternalApi + public void clearInvocationId() { + invocationId.remove(); + } + + @InternalApi + public static HttpRpcContext init() { + return new HttpRpcContext(UUID::randomUUID); + } + + @InternalApi + public static HttpRpcContext getInstance() { + if (instance == null) { + synchronized (GET_INSTANCE_LOCK) { + if (instance == null) { + instance = init(); + } + } + } + return instance; + } +} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index d0c1ff8a96..70f3493295 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -18,6 +18,7 @@ import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import com.google.api.client.googleapis.batch.BatchRequest; @@ -26,6 +27,7 @@ import com.google.api.client.http.ByteArrayContent; import com.google.api.client.http.EmptyContent; import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpExecuteInterceptor; import com.google.api.client.http.HttpHeaders; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestFactory; @@ -86,6 +88,8 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.UUID; +import javax.annotation.Nullable; public class HttpStorageRpc implements StorageRpc { public static final String DEFAULT_PROJECTION = "full"; @@ -114,6 +118,7 @@ public HttpStorageRpc(StorageOptions options) { // Open Census initialization censusHttpModule = new CensusHttpModule(tracer, true); initializer = censusHttpModule.getHttpRequestInitializer(initializer); + initializer = new InvocationIdInitializer(initializer); batchRequestInitializer = censusHttpModule.getHttpRequestInitializer(null); storage = new Storage.Builder(transport, new JacksonFactory(), initializer) @@ -122,6 +127,54 @@ public HttpStorageRpc(StorageOptions options) { .build(); } + private static final class InvocationIdInitializer implements HttpRequestInitializer { + @Nullable HttpRequestInitializer initializer; + + private InvocationIdInitializer(@Nullable HttpRequestInitializer initializer) { + this.initializer = initializer; + } + + @Override + public void initialize(HttpRequest request) throws IOException { + checkNotNull(request); + if (this.initializer != null) { + this.initializer.initialize(request); + } + request.setInterceptor(new InvocationIdInterceptor(request.getInterceptor())); + } + } + + private static final class InvocationIdInterceptor implements HttpExecuteInterceptor { + @Nullable HttpExecuteInterceptor interceptor; + + private InvocationIdInterceptor(@Nullable HttpExecuteInterceptor interceptor) { + this.interceptor = interceptor; + } + + @Override + public void intercept(HttpRequest request) throws IOException { + checkNotNull(request); + if (this.interceptor != null) { + this.interceptor.intercept(request); + } + UUID invocationId = HttpRpcContext.getInstance().getInvocationId(); + final String signatureKey = "Signature="; // For V2 and V4 signedURLs + final String builtURL = request.getUrl().build(); + if (invocationId != null && !builtURL.contains(signatureKey)) { + HttpHeaders headers = request.getHeaders(); + String existing = (String) headers.get("x-goog-api-client"); + String invocationEntry = "gccl-invocation-id/" + invocationId; + final String newValue; + if (existing != null && !existing.isEmpty()) { + newValue = existing + " " + invocationEntry; + } else { + newValue = invocationEntry; + } + headers.set("x-goog-api-client", newValue); + } + } + } + private class DefaultRpcBatch implements RpcBatch { // Batch size is limited as, due to some current service implementation details, the service diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java index 5c9c708c10..ac478ab345 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java @@ -17,10 +17,18 @@ package com.google.cloud.storage; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.cloud.TransportOptions; +import com.google.cloud.Tuple; +import com.google.cloud.http.HttpTransportOptions; +import com.google.cloud.storage.spi.v1.AuditingHttpTransport; +import java.util.Optional; import org.easymock.EasyMock; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; public class StorageOptionsTest { @@ -65,4 +73,54 @@ public void testDefaultInstanceSpecifiesCorrectHost() { assertThat(opts1.getHost()).isEqualTo("https://storage.googleapis.com"); } + + @Test + public void testDefaultInvocationId() { + StorageOptions opts1 = StorageOptions.getDefaultInstance(); + + assertTrue(opts1.isIncludeInvocationId()); + } + + @Test + public void testDisableInvocationId() { + StorageOptions opts1 = StorageOptions.newBuilder().setIncludeInvocationId(false).build(); + + assertFalse(opts1.isIncludeInvocationId()); + } + + /** + * Disabled until {@link StorageOptions#isIncludeInvocationId()} and {@link + * StorageOptions.Builder#setIncludeInvocationId(boolean)} are public. + */ + @Test + @Ignore + public void testInvocationIdIsNotPassedThroughWhenDisabled() { + MockLowLevelHttpResponse response = + new MockLowLevelHttpResponse() + .setContentType("application/json") + .setContent( + "{\n" + + " \"kind\": \"storage#serviceAccount\",\n" + + " \"email_address\": \"service-234234@gs-project-accounts.iam.gserviceaccount.com\"\n" + + "}\n") + .setStatusCode(200); + AuditingHttpTransport transport = new AuditingHttpTransport(response); + TransportOptions transportOptions = + HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build(); + Storage service = + StorageOptions.getDefaultInstance() + .toBuilder() + .setTransportOptions(transportOptions) + .setIncludeInvocationId(false) + .build() + .getService(); + service.getServiceAccount("test-project"); + Optional> anyXGoogApiClientWithGcclInvocationId = + transport.getAddHeaderCalls().stream() + .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/")) + .findFirst(); + + assertFalse(anyXGoogApiClientWithGcclInvocationId.isPresent()); + assertThat(transport.getBuildRequestCalls()).hasSize(1); + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 80d1ebc384..d755d38d2a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -3560,6 +3560,16 @@ public void testBucketLocationType() throws ExecutionException, InterruptedExcep RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); } + @Test + public void testBucketLocationDualRegion() { + String bucketName = RemoteStorageHelper.generateBucketName(); + String dualRegionLocation = "US-EAST1+US-WEST1"; + Bucket bucket = + storage.create(BucketInfo.newBuilder(bucketName).setLocation(dualRegionLocation).build()); + assertEquals(bucket.getLocation(), dualRegionLocation); + assertEquals(bucket.getLocationType(), "dual-region"); + } + @Test public void testBucketLogging() throws ExecutionException, InterruptedException { String logsBucket = RemoteStorageHelper.generateBucketName(); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java new file mode 100644 index 0000000000..edb7d64c14 --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java @@ -0,0 +1,62 @@ +/* + * Copyright 2022 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.google.cloud.storage.spi.v1; + +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.LowLevelHttpRequest; +import com.google.api.client.http.LowLevelHttpResponse; +import com.google.cloud.Tuple; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class AuditingHttpTransport extends HttpTransport { + private final LowLevelHttpResponse response; + private final List> buildRequestCalls; + private final List> addHeaderCalls; + + public AuditingHttpTransport(LowLevelHttpResponse response) { + this.response = response; + this.buildRequestCalls = Collections.synchronizedList(new ArrayList<>()); + this.addHeaderCalls = Collections.synchronizedList(new ArrayList<>()); + } + + public List> getBuildRequestCalls() { + return ImmutableList.copyOf(buildRequestCalls); + } + + public List> getAddHeaderCalls() { + return ImmutableList.copyOf(addHeaderCalls); + } + + @Override + protected LowLevelHttpRequest buildRequest(String method, String url) { + buildRequestCalls.add(Tuple.of(method, url)); + return new LowLevelHttpRequest() { + @Override + public void addHeader(String name, String value) { + addHeaderCalls.add(Tuple.of(name, value)); + } + + @Override + public LowLevelHttpResponse execute() { + return response; + } + }; + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java new file mode 100644 index 0000000000..3e8b295bda --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2022 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.google.cloud.storage.spi.v1; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.api.client.testing.http.MockLowLevelHttpResponse; +import com.google.cloud.TransportOptions; +import com.google.cloud.Tuple; +import com.google.cloud.WriteChannel; +import com.google.cloud.http.HttpTransportOptions; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.UUID; +import org.junit.Test; + +public class HttpRpcContextTest { + @Test + public void testNewInvocationId() { + UUID uuid = UUID.fromString("28220dff-1e8b-4770-9e10-022c2a99d8f3"); + HttpRpcContext testContext = new HttpRpcContext(() -> uuid); + + assertThat(testContext.newInvocationId()).isEqualTo(uuid); + assertThat(testContext.getInvocationId()).isEqualTo(uuid); + // call again to ensure the id is consistent with our supplier + assertThat(testContext.newInvocationId()).isEqualTo(uuid); + assertThat(testContext.getInvocationId()).isEqualTo(uuid); + } + + @Test + public void testInvocationIdIsPassedThrough() { + MockLowLevelHttpResponse response = + new MockLowLevelHttpResponse() + .setContentType("application/json") + .setContent( + "{\n" + + " \"kind\": \"storage#serviceAccount\",\n" + + " \"email_address\": \"service-234234@gs-project-accounts.iam.gserviceaccount.com\"\n" + + "}\n") + .setStatusCode(200); + AuditingHttpTransport transport = new AuditingHttpTransport(response); + TransportOptions transportOptions = + HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build(); + Storage service = + StorageOptions.getDefaultInstance() + .toBuilder() + .setTransportOptions(transportOptions) + .build() + .getService(); + service.getServiceAccount("test-project"); + Optional> anyXGoogApiClientWithGcclInvocationId = + transport.getAddHeaderCalls().stream() + .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/")) + .findFirst(); + assertTrue(anyXGoogApiClientWithGcclInvocationId.isPresent()); + assertThat(transport.getBuildRequestCalls()).hasSize(1); + } + + @Test + public void testInvocationIdNotInSignedURL_v2() throws IOException { + URL signedUrlV2 = + new URL( + "http://www.test.com/test-bucket/test1.txt?GoogleAccessId=testClient-test@test.com&Expires=1553839761&Signature=MJUBXAZ7"); + doTestInvocationIdNotInSignedURL(signedUrlV2); + } + + @Test + public void testInvocationIdNotInSignedURL_v4() throws IOException { + URL signedUrlV4 = + new URL( + "http://www.test.com/test-bucket/test1.txt?X-Goog-Algorithm=&X-Goog-Credential=&X-Goog-Date=&X-Goog-Expires=&X-Goog-SignedHeaders=&X-Goog-Signature=MJUBXAZ7"); + doTestInvocationIdNotInSignedURL(signedUrlV4); + } + + private void doTestInvocationIdNotInSignedURL(URL signedUrl) throws IOException { + MockLowLevelHttpResponse response = + new MockLowLevelHttpResponse() + .setContentType("text/plain") + .setHeaderNames(ImmutableList.of("Location")) + .setHeaderValues(ImmutableList.of("http://test")) + .setStatusCode(201); + AuditingHttpTransport transport = new AuditingHttpTransport(response); + TransportOptions transportOptions = + HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build(); + Storage service = + StorageOptions.getDefaultInstance() + .toBuilder() + .setTransportOptions(transportOptions) + .build() + .getService(); + WriteChannel writer = service.writer(signedUrl); + writer.write(ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8))); + Optional> anyXGoogApiClientWithGcclInvocationId = + transport.getAddHeaderCalls().stream() + .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/")) + .findFirst(); + assertFalse(anyXGoogApiClientWithGcclInvocationId.isPresent()); + assertThat(transport.getBuildRequestCalls()).hasSize(1); + } +} diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml index 4516cf7add..27a037d1ad 100644 --- a/grpc-google-cloud-storage-v2/pom.xml +++ b/grpc-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha grpc-google-cloud-storage-v2 GRPC library for grpc-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.6.0 + 2.6.1 diff --git a/owlbot.py b/owlbot.py index 2b33b683f4..c94718a388 100644 --- a/owlbot.py +++ b/owlbot.py @@ -33,5 +33,6 @@ '.kokoro/nightly/samples.cfg', '.kokoro/presubmit/integration.cfg', '.kokoro/presubmit/samples.cfg', + '.kokoro/presubmit/graalvm-native.cfg', 'CONTRIBUTING.md' ]) diff --git a/pom.xml b/pom.xml index 5daef9d926..b9823efc72 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-storage-parent pom - 2.6.0 + 2.6.1 Storage Parent https://github.com/googleapis/java-storage @@ -54,7 +54,7 @@ UTF-8 github google-cloud-storage-parent - 2.9.0 + 2.10.0 @@ -70,17 +70,17 @@ com.google.cloud google-cloud-storage - 2.6.0 + 2.6.1 com.google.apis google-api-services-storage - v1-rev20220210-1.32.1 + v1-rev20220401-1.32.1 com.google.cloud google-cloud-pubsub - 1.116.2 + 1.116.3 test @@ -111,22 +111,22 @@ com.google.api.grpc proto-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha com.google.api.grpc grpc-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha com.google.api.grpc gapic-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha com.google.cloud google-cloud-conformance-tests - 0.2.9 + 0.2.10 test diff --git a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml index 2fafe5526e..fc73daacd1 100644 --- a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml +++ b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml @@ -1,164 +1,4 @@ - - 7012 - com/google/storage/v2/*OrBuilder - * get*(*) - - - 7012 - com/google/storage/v2/*OrBuilder - boolean contains*(*) - - - 7012 - com/google/storage/v2/*OrBuilder - boolean has*(*) - - - - - 6011 - com/google/storage/v2/* - ZONE_AFFINITY_FIELD_NUMBER - - - 7002 - com/google/storage/v2/* - * *ZoneAffinity*(*) - - - - - - - 7005 - com/google/storage/v2/Object* - * *CustomerEncryption*(*) - * - - - - 7006 - com/google/storage/v2/Object* - * *CustomerEncryption*(*) - * - - - - 8001 - com/google/storage/v2/Object$CustomerEncryption* - - - - - - 6011 - com/google/storage/v2/* - CUSTOM_PLACEMENT_CONFIG_FIELD_NUMBER - - - - 7002 - com/google/storage/v2/* - * *CustomPlacementConfig*(*) - - - 7002 - com/google/storage/v2/* - * *DestinationPredefinedAclValue*(*) - - - 7002 - com/google/storage/v2/* - * *PredefinedAclValue*(*) - - - 7002 - com/google/storage/v2/* - * *PredefinedDefaultObjectAclValue*(*) - - - 7002 - com/google/storage/v2/* - * *PublicAccessPrevention*(*) - - - - 7005 - com/google/storage/v2/Bucket$IamConfig$Builder - com.google.storage.v2.Bucket$IamConfig$Builder setPublicAccessPrevention(com.google.storage.v2.Bucket$IamConfig$PublicAccessPrevention) - com.google.storage.v2.Bucket$IamConfig$Builder setPublicAccessPrevention(java.lang.String) - - - - - - 7005 - com/google/storage/v2/* - * *(*) - * *(*) - - - - - 7006 - com/google/storage/v2/* - * *DestinationPredefinedAcl*(*) - * - - - 7006 - com/google/storage/v2/* - * *PredefinedAcl*(*) - * - - - 7006 - com/google/storage/v2/* - * *PredefinedDefaultObjectAcl*(*) - * - - - 7006 - com/google/storage/v2/* - * *PublicAccessPrevention*(*) - * - - - - 8001 - com/google/storage/v2/Bucket$CustomPlacementConfig* - - - 8001 - com/google/storage/v2/Bucket$IamConfig$PublicAccessPrevention* - - - 8001 - com/google/storage/v2/PredefinedBucketAcl - - - 8001 - com/google/storage/v2/PredefinedObjectAcl - - diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml index 7fd3675edb..49fe243350 100644 --- a/proto-google-cloud-storage-v2/pom.xml +++ b/proto-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-storage-v2 - 2.6.0-alpha + 2.6.1-alpha proto-google-cloud-storage-v2 PROTO library for proto-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.6.0 + 2.6.1 diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 16815493c4..add9193868 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -15,6 +15,7 @@ com.google.cloud.samples shared-configuration 1.2.0 + @@ -29,7 +30,7 @@ com.google.cloud google-cloud-storage - 2.5.1 + 2.6.0 @@ -57,6 +58,12 @@ 4.5.13 test + + com.google.cloud + google-cloud-pubsub + 1.116.3 + test + diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index 8d98f37e14..711438da3a 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -14,6 +14,7 @@ com.google.cloud.samples shared-configuration 1.2.0 + @@ -28,7 +29,7 @@ com.google.cloud libraries-bom - 25.0.0 + 25.1.0 pom import @@ -57,6 +58,12 @@ 1.1.3 test + + com.google.cloud + google-cloud-pubsub + 1.116.3 + test + @@ -107,7 +114,7 @@ com.google.cloud native-image-support - 0.12.10 + 0.13.1 org.junit.vintage @@ -170,4 +177,4 @@ - \ No newline at end of file + diff --git a/samples/pom.xml b/samples/pom.xml index 2c01e6fca0..8de92bd400 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -19,6 +19,7 @@ com.google.cloud.samples shared-configuration 1.2.0 + diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 6cd97d6cc0..e7bab3f8df 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -15,6 +15,7 @@ com.google.cloud.samples shared-configuration 1.2.0 + @@ -27,7 +28,7 @@ com.google.cloud google-cloud-storage - 2.6.0 + 2.6.1 @@ -48,6 +49,12 @@ 4.5.13 test + + com.google.cloud + google-cloud-pubsub + 1.116.3 + test + @@ -84,4 +91,4 @@ - \ No newline at end of file + diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 292403d526..01df9ad79e 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -15,6 +15,7 @@ com.google.cloud.samples shared-configuration 1.2.0 + @@ -30,7 +31,7 @@ com.google.cloud libraries-bom - 25.0.0 + 25.1.0 pom import @@ -56,5 +57,23 @@ 1.1.3 test + + org.apache.httpcomponents + httpclient + 4.5.13 + test + + + org.apache.httpcomponents + httpmime + 4.5.13 + test + + + com.google.cloud + google-cloud-pubsub + 1.116.3 + test + diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java new file mode 100644 index 0000000000..e5a3fccb0d --- /dev/null +++ b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java @@ -0,0 +1,54 @@ +/* + * Copyright 2022 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.storage.bucket; + +// [START storage_create_bucket_dual_region] + +import com.google.cloud.storage.Bucket; +import com.google.cloud.storage.BucketInfo; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; + +public class CreateBucketDualRegion { + + public static void createBucketDualRegion( + String projectId, String bucketName, String firstRegion, String secondRegion) { + // The ID of your GCP project + // String projectId = "your-project-id"; + + // The ID to give your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // One of the regions the dual region bucket is to be created in. + // String firstRegion = "US-EAST1"; + + // The second region the dual region bucket is to be created in. + // String secondRegion = "US-WEST1"; + + // Construct the dual region ie. "US-EAST1+US-WEST1" + String dualRegion = firstRegion + "+" + secondRegion; + + Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService(); + + Bucket bucket = + storage.create(BucketInfo.newBuilder(bucketName).setLocation(dualRegion).build()); + + System.out.println( + "Created bucket " + bucket.getName() + " in location " + bucket.getLocation()); + } +} +// [END storage_create_bucket_dual_region] diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java new file mode 100644 index 0000000000..da2b3b3d13 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java @@ -0,0 +1,65 @@ +/* + * Copyright 2022 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.storage.bucket; + +// [START storage_create_bucket_notifications] +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; +import com.google.cloud.storage.NotificationInfo.EventType; +import com.google.cloud.storage.NotificationInfo.PayloadFormat; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import java.util.Map; + +public class CreateBucketPubSubNotification { + + public static void createBucketPubSubNotification( + String bucketName, + String topicName, + Map customAttributes, + EventType[] eventTypes, + String objectNamePrefix, + PayloadFormat payloadFormat) { + // The ID to give your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The name of the topic you would like to create a notification for + // String topicName = "projects/{your-project}/topics/{your-topic}"; + + // Any custom attributes + // Map customAttributes = Map.of("label", "value"); + + // The object name prefix for which this notification configuration applies + // String objectNamePrefix = "blob-"; + + // Desired content of the Payload + // PayloadFormat payloadFormat = PayloadFormat.JSON_API_V1.JSON_API_V1; + + Storage storage = StorageOptions.newBuilder().build().getService(); + NotificationInfo notificationInfo = + NotificationInfo.newBuilder(topicName) + .setCustomAttributes(customAttributes) + .setEventTypes(eventTypes) + .setObjectNamePrefix(objectNamePrefix) + .setPayloadFormat(payloadFormat) + .build(); + Notification notification = storage.createNotification(bucketName, notificationInfo); + String topic = notification.getTopic(); + System.out.println("Successfully created notification for topic " + topic); + } +} +// [END storage_create_bucket_notifications] diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java new file mode 100644 index 0000000000..dd59e2e189 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022 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.storage.bucket; + +// [START storage_delete_bucket_notification] +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; + +public class DeleteBucketPubSubNotification { + + public static void deleteBucketPubSubNotification(String bucketName, String notificationId) { + // The ID to give your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The NotificationId for the notification you would like to delete + // String notificationId = "your-unique-notification-id" + + Storage storage = StorageOptions.newBuilder().build().getService(); + boolean success = storage.deleteNotification(bucketName, notificationId); + if (success) { + System.out.println("Successfully deleted notification"); + } else { + System.out.println("Failed to find notification"); + } + } +} +// [END storage_delete_bucket_notification] diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java b/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java new file mode 100644 index 0000000000..b3fb614f8b --- /dev/null +++ b/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java @@ -0,0 +1,39 @@ +/* + * Copyright 2022 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.storage.bucket; + +// [START storage_list_bucket_notifications] +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import java.util.List; + +public class ListPubSubNotifications { + + public static void listPubSubNotifications(String bucketName) { + // The ID to give your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + Storage storage = StorageOptions.newBuilder().build().getService(); + List notificationList = storage.listNotifications(bucketName); + for (Notification notification : notificationList) { + System.out.println( + "Found notification " + notification.getTopic() + " for bucket " + bucketName); + } + } +} +// [END storage_list_bucket_notifications] diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java new file mode 100644 index 0000000000..083a0b551a --- /dev/null +++ b/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java @@ -0,0 +1,39 @@ +/* + * Copyright 2022 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.storage.bucket; + +// [START storage_print_pubsub_bucket_notification] +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; + +public class PrintPubSubNotification { + + public static void printPubSubNotification(String bucketName, String notificationId) { + // The ID to give your GCS bucket + // String bucketName = "your-unique-bucket-name"; + + // The Pub/Sub topic you would like to find + // String notificationId = "your-unique-notification-id" + + Storage storage = StorageOptions.newBuilder().build().getService(); + Notification notification = storage.getNotification(bucketName, notificationId); + System.out.println( + "Found notification " + notification.getTopic() + " for bucket " + bucketName); + } +} +// [END storage_print_pubsub_bucket_notification] diff --git a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java index 822c3189c9..6d434e30ed 100644 --- a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java +++ b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java @@ -81,12 +81,9 @@ import com.google.cloud.storage.Storage; import com.google.cloud.storage.StorageRoles; import com.google.cloud.storage.testing.RemoteStorageHelper; +import com.google.cloud.testing.junit4.StdOutCaptureRule; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.io.ByteArrayOutputStream; -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Map; @@ -111,10 +108,11 @@ public class ITBucketSnippets { private static final String KMS_KEY_NAME = "projects/java-docs-samples-testing/locations/us/keyRings/" + "jds_test_kms_key_ring/cryptoKeys/gcs_kms_key_one"; - private final PrintStream standardOut = new PrintStream(new FileOutputStream(FileDescriptor.out)); private static Storage storage; + @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Rule public Timeout globalTimeout = Timeout.seconds(300); @@ -152,9 +150,6 @@ public static void afterClass() throws ExecutionException, InterruptedException public void after() throws Exception { // This avoids 429 errors Thread.sleep(3000); - - // This is just in case any tests failed before they could reset the value - System.setOut(standardOut); } @Test @@ -231,12 +226,8 @@ public void testGetBucketMetadata() { .build() .update(); - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetBucketMetadata.getBucketMetadata(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); - System.out.println(snippetOutput); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains(("BucketName: " + bucket.getName()))); assertTrue( snippetOutput.contains(("DefaultEventBasedHold: " + bucket.getDefaultEventBasedHold()))); @@ -264,11 +255,8 @@ public void testGetBucketMetadata() { @Test public void testListBuckets() { - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); ListBuckets.listBuckets(PROJECT_ID); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains(BUCKET)); } @@ -320,11 +308,8 @@ public void testGetPublicAccessPrevention() { .build()) .build() .update(); - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetPublicAccessPrevention.getPublicAccessPrevention(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("enforced")); storage .get(BUCKET) @@ -421,11 +406,8 @@ public void testAddListRemoveBucketIamMembers() { int originalSize = storage.getIamPolicy(BUCKET).getBindingsList().size(); AddBucketIamMember.addBucketIamMember(PROJECT_ID, BUCKET); assertEquals(originalSize + 1, storage.getIamPolicy(BUCKET).getBindingsList().size()); - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); ListBucketIamMembers.listBucketIamMembers(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("example@google.com")); RemoveBucketIamMember.removeBucketIamMember(PROJECT_ID, BUCKET); assertEquals(originalSize, storage.getIamPolicy(BUCKET).getBindingsList().size()); @@ -486,11 +468,8 @@ public void testSetBucketWebsiteInfo() { @Test public void testSetClientEndpoint() { - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); SetClientEndpoint.setClientEndpoint(PROJECT_ID, "https://storage.googleapis.com"); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("https://storage.googleapis.com")); } @@ -566,11 +545,8 @@ public void testRpo() throws Exception { bucket = storage.get(rpoBucket); assertEquals("ASYNC_TURBO", bucket.getRpo().toString()); - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetBucketRpo.getBucketRpo(PROJECT_ID, rpoBucket); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("ASYNC_TURBO")); } finally { storage.delete(rpoBucket); @@ -594,21 +570,16 @@ public void testBucketRetention() { assertEquals(retention, bucket.getRetentionPeriod()); assertNotNull(bucket.getRetentionEffectiveTime()); - ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetRetentionPolicy.getRetentionPolicy(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("5")); EnableDefaultEventBasedHold.enableDefaultEventBasedHold(PROJECT_ID, BUCKET); assertTrue(storage.get(BUCKET).getDefaultEventBasedHold()); - snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetDefaultEventBasedHold.getDefaultEventBasedHold(PROJECT_ID, BUCKET); - snippetOutput = snippetOutputCapture.toString(); + snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("enabled")); - System.setOut(standardOut); byte[] content = {0xD, 0xE, 0xA, 0xD}; String blobName = "test-create-empty-blob-retention-policy"; @@ -645,12 +616,9 @@ public void testUniformBucketLevelAccess() { assertTrue(bucket.getIamConfiguration().isUniformBucketLevelAccessEnabled()); assertNotNull(bucket.getIamConfiguration().getUniformBucketLevelAccessLockedTime()); - ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetUniformBucketLevelAccess.getUniformBucketLevelAccess(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("enabled")); - System.setOut(standardOut); DisableUniformBucketLevelAccess.disableUniformBucketLevelAccess(PROJECT_ID, BUCKET); assertFalse(storage.get(BUCKET).getIamConfiguration().isUniformBucketLevelAccessEnabled()); diff --git a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java index 6c6886eb53..3cb572dc94 100644 --- a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java +++ b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java @@ -61,16 +61,13 @@ import com.google.cloud.storage.Storage.BlobListOption; import com.google.cloud.storage.StorageClass; import com.google.cloud.storage.testing.RemoteStorageHelper; +import com.google.cloud.testing.junit4.StdOutCaptureRule; import com.google.common.collect.ImmutableMap; import com.google.common.io.BaseEncoding; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileDescriptor; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.PrintStream; import java.net.URL; import java.nio.file.Files; import java.util.Date; @@ -83,7 +80,6 @@ import javax.net.ssl.HttpsURLConnection; import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; @@ -97,13 +93,14 @@ public class ITObjectSnippets { private static final String STRING_CONTENT = "Hello, World!"; private static final byte[] CONTENT = STRING_CONTENT.getBytes(UTF_8); private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); - private final PrintStream standardOut = new PrintStream(new FileOutputStream(FileDescriptor.out)); private static final String KMS_KEY_NAME = "projects/java-docs-samples-testing/locations/us/keyRings/" + "jds_test_kms_key_ring/cryptoKeys/gcs_kms_key_one"; private static Storage storage; + @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule(); + @Rule public ExpectedException thrown = ExpectedException.none(); @BeforeClass @@ -127,12 +124,6 @@ public static void afterClass() throws ExecutionException, InterruptedException } } - @Before - public void before() { - // This is just in case any tests failed before they could reset the value - System.setOut(standardOut); - } - @Test public void testChangeObjectStorageClass() { Blob blob = storage.get(BUCKET, BLOB); @@ -177,12 +168,8 @@ public void testDownloadObject() throws IOException { @Test public void testDownloadObjectIntoMemory() throws IOException { - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); DownloadObjectIntoMemory.downloadObjectIntoMemory(PROJECT_ID, BUCKET, BLOB); - String snippetOutput = snippetOutputCapture.toString(); - assertTrue(snippetOutput.contains("Hello, World!")); - System.setOut(standardOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); } @Test @@ -207,12 +194,8 @@ public void testGetObjectMetadata() { BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setMetadata(ImmutableMap.of("k", "v")).build(); Blob remoteBlob = storage.create(blobInfo, CONTENT); assertNotNull(remoteBlob); - final PrintStream systemOut = System.out; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetObjectMetadata.getObjectMetadata(PROJECT_ID, BUCKET, blobName); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(systemOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("Bucket: " + remoteBlob.getBucket())); assertTrue(snippetOutput.contains("Bucket: " + remoteBlob.getBucket())); assertTrue(snippetOutput.contains("CacheControl: " + remoteBlob.getCacheControl())); @@ -246,28 +229,21 @@ public void testGetObjectMetadata() { @Test public void testListObjects() { - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); ListObjects.listObjects(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains(BLOB)); - System.setOut(standardOut); } @Test public void testListObjectsWithPrefix() { - final PrintStream systemOutput = System.out; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/1.txt")).build()); storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/b/2.txt")).build()); storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/b/3.txt")).build()); ListObjectsWithPrefix.listObjectsWithPrefix(PROJECT_ID, BUCKET, "a/"); - String snippetOutput = snippetOutputCapture.toString(); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("a/1.txt")); assertTrue(snippetOutput.contains("a/b/")); assertFalse(snippetOutput.contains("a/b/2.txt")); - System.setOut(systemOutput); } @Test @@ -318,13 +294,8 @@ public void testUploadObjectFromMemory() throws IOException { @Test public void testObjectCSEKOperations() throws IOException { - final PrintStream systemOut = System.out; - - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GenerateEncryptionKey.generateEncryptionKey(); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(systemOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); String encryptionKey = snippetOutput.split(": ")[1].trim(); File tempFile = File.createTempFile("file", ".txt"); @@ -363,12 +334,8 @@ public void testObjectVersioningOperations() { byte[] content2 = "Hello, World 2".getBytes(UTF_8); storage.create(BlobInfo.newBuilder(BUCKET, versionedBlob).build(), content2); - final PrintStream systemOut = System.out; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); ListObjectsWithOldVersions.listObjectsWithOldVersions(PROJECT_ID, BUCKET); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(systemOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); snippetOutput = snippetOutput.replaceFirst(versionedBlob, ""); assertTrue(snippetOutput.contains(versionedBlob)); @@ -386,10 +353,8 @@ public void testObjectVersioningOperations() { @Test public void testV4SignedURLs() throws IOException { String tempObject = "test-upload-signed-url-object"; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GenerateV4PutObjectSignedUrl.generateV4PutObjectSignedUrl(PROJECT_ID, BUCKET, tempObject); - String snippetOutput = snippetOutputCapture.toString(); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); String url = snippetOutput.split("\n")[1]; URL uploadUrl = new URL(url); HttpsURLConnection connection = (HttpsURLConnection) uploadUrl.openConnection(); @@ -401,10 +366,9 @@ public void testV4SignedURLs() throws IOException { assertEquals(connection.getResponseCode(), 200); } GenerateV4GetObjectSignedUrl.generateV4GetObjectSignedUrl(PROJECT_ID, BUCKET, tempObject); - snippetOutput = snippetOutputCapture.toString(); + snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); url = snippetOutput.split("\n")[5]; URL downloadUrl = new URL(url); - System.setOut(standardOut); connection = (HttpsURLConnection) downloadUrl.openConnection(); byte[] readBytes = new byte[CONTENT.length]; try (InputStream responseStream = connection.getInputStream()) { diff --git a/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java index 092a681a7d..3c448def64 100644 --- a/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java +++ b/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java @@ -22,10 +22,9 @@ import com.google.cloud.storage.BucketInfo; import com.google.cloud.storage.Storage; import com.google.cloud.storage.testing.RemoteStorageHelper; -import java.io.ByteArrayOutputStream; +import com.google.cloud.testing.junit4.StdOutCaptureRule; import java.io.File; import java.io.FileInputStream; -import java.io.PrintStream; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; @@ -52,6 +51,8 @@ public class ITStorageSnippets { private static Storage storage; private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Rule public Timeout globalTimeout = Timeout.seconds(300); @@ -81,12 +82,8 @@ public static void afterClass() throws ExecutionException, InterruptedException @Test public void testGetServiceAccount() { - PrintStream systemOut = System.out; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GetServiceAccount.getServiceAccount(PROJECT_ID); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(systemOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue(snippetOutput.contains("service")); assertTrue(snippetOutput.contains("@gs-project-accounts.iam.gserviceaccount.com")); @@ -94,12 +91,8 @@ public void testGetServiceAccount() { @Test public void testGenerateSignedPostPolicyV4() throws Exception { - PrintStream systemOut = System.out; - final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream(); - System.setOut(new PrintStream(snippetOutputCapture)); GenerateSignedPostPolicyV4.generateSignedPostPolicyV4(PROJECT_ID, BUCKET, "my-object"); - String snippetOutput = snippetOutputCapture.toString(); - System.setOut(systemOut); + String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String(); assertTrue( snippetOutput.contains("
CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final String PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String TOPIC = String.format("projects/%s/topics/new-topic-create", PROJECT); + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final EventType[] EVENT_TYPES = { + EventType.OBJECT_FINALIZE, EventType.OBJECT_METADATA_UPDATE + }; + private static TopicAdminClient topicAdminClient; + + @BeforeClass + public static void configureTopicAdminClient() throws IOException { + if (PROJECT != null) { + topicAdminClient = TopicAdminClient.create(); + topicAdminClient.createTopic(TOPIC); + GetIamPolicyRequest getIamPolicyRequest = + GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); + com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(getIamPolicyRequest); + Binding binding = + Binding.newBuilder().setRole("roles/owner").addMembers("allAuthenticatedUsers").build(); + SetIamPolicyRequest setIamPolicyRequest = + SetIamPolicyRequest.newBuilder() + .setResource(TOPIC) + .setPolicy(policy.toBuilder().addBindings(binding).build()) + .build(); + topicAdminClient.setIamPolicy(setIamPolicyRequest); + } + } + + @AfterClass + public static void deleteTopicAndClient() { + /* Delete the Pub/Sub topic */ + if (topicAdminClient != null) { + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); + } + } + + @Test + public void testCreateBucketPubSubNotification() { + // Check that we can access project value and that topic admin client came up successfully + assertNotNull("Unable to determine project", PROJECT); + assertNotNull("Topic Admin Client did not start up", topicAdminClient); + + com.example.storage.bucket.CreateBucketPubSubNotification.createBucketPubSubNotification( + bucketName, TOPIC, CUSTOM_ATTRIBUTES, EVENT_TYPES, OBJECT_NAME_PREFIX, PAYLOAD_FORMAT); + assertThat(stdOut.getCapturedOutputAsUtf8String()).contains(TOPIC); + } +} diff --git a/samples/snippets/src/test/java/com/example/storage/bucket/DeleteBucketPubSubNotificationTest.java b/samples/snippets/src/test/java/com/example/storage/bucket/DeleteBucketPubSubNotificationTest.java new file mode 100644 index 0000000000..e094f33469 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/storage/bucket/DeleteBucketPubSubNotificationTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2022 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.storage.bucket; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; + +import com.example.storage.TestBase; +import com.google.cloud.pubsub.v1.TopicAdminClient; +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; +import com.google.common.collect.ImmutableMap; +import com.google.iam.v1.Binding; +import com.google.iam.v1.GetIamPolicyRequest; +import com.google.iam.v1.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Map; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class DeleteBucketPubSubNotificationTest extends TestBase { + + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final String PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String TOPIC = String.format("projects/%s/topics/new-topic-delete", PROJECT); + private static TopicAdminClient topicAdminClient; + private static final NotificationInfo notificationInfo = + NotificationInfo.newBuilder(TOPIC) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + + @BeforeClass + public static void configureTopicAdminClient() throws IOException { + if (PROJECT != null) { + topicAdminClient = TopicAdminClient.create(); + topicAdminClient.createTopic(TOPIC); + GetIamPolicyRequest getIamPolicyRequest = + GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); + com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(getIamPolicyRequest); + Binding binding = + Binding.newBuilder().setRole("roles/owner").addMembers("allAuthenticatedUsers").build(); + SetIamPolicyRequest setIamPolicyRequest = + SetIamPolicyRequest.newBuilder() + .setResource(TOPIC) + .setPolicy(policy.toBuilder().addBindings(binding).build()) + .build(); + topicAdminClient.setIamPolicy(setIamPolicyRequest); + } + } + + @AfterClass + public static void deleteTopicAndClient() { + /* Delete the Pub/Sub topic */ + if (topicAdminClient != null) { + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); + } + } + + @Test + public void testDeleteBucketPubSubNotification() { + // Check that we can access project value and that topic admin client came up successfully + assertNotNull("Unable to determine project", PROJECT); + assertNotNull("Topic Admin Client did not start up", topicAdminClient); + + Notification notification = storage.createNotification(bucketName, notificationInfo); + com.example.storage.bucket.DeleteBucketPubSubNotification.deleteBucketPubSubNotification( + bucketName, notification.getNotificationId()); + assertThat(stdOut.getCapturedOutputAsUtf8String()) + .contains("Successfully deleted notification"); + } + + @Test + public void testNotificationNotFound() { + // Check that we can access project value and that topic admin client came up successfully + assertNotNull("Unable to determine project", PROJECT); + assertNotNull("Topic Admin Client did not start up", topicAdminClient); + Notification notification = storage.createNotification(bucketName, notificationInfo); + // Do a delete first. + storage.deleteNotification(bucketName, notification.getNotificationId()); + // Now try to delete again. + com.example.storage.bucket.DeleteBucketPubSubNotification.deleteBucketPubSubNotification( + bucketName, notification.getNotificationId()); + assertThat(stdOut.getCapturedOutputAsUtf8String()).contains("Failed to find notification"); + } +} diff --git a/samples/snippets/src/test/java/com/example/storage/bucket/ListPubSubNotificationsTest.java b/samples/snippets/src/test/java/com/example/storage/bucket/ListPubSubNotificationsTest.java new file mode 100644 index 0000000000..c7dee85472 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/storage/bucket/ListPubSubNotificationsTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2022 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.storage.bucket; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; + +import com.example.storage.TestBase; +import com.google.cloud.pubsub.v1.TopicAdminClient; +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; +import com.google.common.collect.ImmutableMap; +import com.google.iam.v1.Binding; +import com.google.iam.v1.GetIamPolicyRequest; +import com.google.iam.v1.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Map; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ListPubSubNotificationsTest extends TestBase { + + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final String PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String TOPIC = String.format("projects/%s/topics/new-topic-list", PROJECT); + private static TopicAdminClient topicAdminClient; + + @BeforeClass + public static void configureTopicAdminClient() throws IOException { + if (PROJECT != null) { + topicAdminClient = TopicAdminClient.create(); + topicAdminClient.createTopic(TOPIC); + GetIamPolicyRequest getIamPolicyRequest = + GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); + com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(getIamPolicyRequest); + Binding binding = + Binding.newBuilder().setRole("roles/owner").addMembers("allAuthenticatedUsers").build(); + SetIamPolicyRequest setIamPolicyRequest = + SetIamPolicyRequest.newBuilder() + .setResource(TOPIC) + .setPolicy(policy.toBuilder().addBindings(binding).build()) + .build(); + topicAdminClient.setIamPolicy(setIamPolicyRequest); + } + } + + @AfterClass + public static void deleteTopicAndClient() { + /* Delete the Pub/Sub topic */ + if (topicAdminClient != null) { + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); + } + } + + @Test + public void testListBucketPubSubNotification() { + // Check that we can access project value and that topic admin client came up successfully + assertNotNull("Unable to determine project", PROJECT); + assertNotNull("Topic Admin Client did not start up", topicAdminClient); + + NotificationInfo notificationInfo = + NotificationInfo.newBuilder(TOPIC) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + storage.createNotification(bucketName, notificationInfo); + ListPubSubNotifications.listPubSubNotifications(bucketName); + assertThat(stdOut.getCapturedOutputAsUtf8String()).contains(TOPIC); + } +} diff --git a/samples/snippets/src/test/java/com/example/storage/bucket/PrintPubSubNotificationTest.java b/samples/snippets/src/test/java/com/example/storage/bucket/PrintPubSubNotificationTest.java new file mode 100644 index 0000000000..05526675ff --- /dev/null +++ b/samples/snippets/src/test/java/com/example/storage/bucket/PrintPubSubNotificationTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2022 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.storage.bucket; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; + +import com.example.storage.TestBase; +import com.google.cloud.pubsub.v1.TopicAdminClient; +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; +import com.google.common.collect.ImmutableMap; +import com.google.iam.v1.Binding; +import com.google.iam.v1.GetIamPolicyRequest; +import com.google.iam.v1.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Map; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PrintPubSubNotificationTest extends TestBase { + + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final String PROJECT = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String TOPIC = String.format("projects/%s/topics/new-topic-print", PROJECT); + private static TopicAdminClient topicAdminClient; + + @BeforeClass + public static void configureTopicAdminClient() throws IOException { + if (PROJECT != null) { + topicAdminClient = TopicAdminClient.create(); + topicAdminClient.createTopic(TOPIC); + GetIamPolicyRequest getIamPolicyRequest = + GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); + com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(getIamPolicyRequest); + Binding binding = + Binding.newBuilder().setRole("roles/owner").addMembers("allAuthenticatedUsers").build(); + SetIamPolicyRequest setIamPolicyRequest = + SetIamPolicyRequest.newBuilder() + .setResource(TOPIC) + .setPolicy(policy.toBuilder().addBindings(binding).build()) + .build(); + topicAdminClient.setIamPolicy(setIamPolicyRequest); + } + } + + @AfterClass + public static void deleteTopicAndClient() { + /* Delete the Pub/Sub topic */ + if (topicAdminClient != null) { + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); + } + } + + @Test + public void testPrintBucketPubSubNotification() { + // Check that we can access project value and that topic admin client came up successfully + assertNotNull("Unable to determine project", PROJECT); + assertNotNull("Topic Admin Client did not start up", topicAdminClient); + + NotificationInfo notificationInfo = + NotificationInfo.newBuilder(TOPIC) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + Notification notification = storage.createNotification(bucketName, notificationInfo); + PrintPubSubNotification.printPubSubNotification(bucketName, notification.getNotificationId()); + assertThat(stdOut.getCapturedOutputAsUtf8String()).contains(TOPIC); + } +} diff --git a/versions.txt b/versions.txt index 2f5fb176bc..f4d29bbad5 100644 --- a/versions.txt +++ b/versions.txt @@ -1,7 +1,7 @@ # Format: # module:released-version:current-version -google-cloud-storage:2.6.0:2.6.0 -gapic-google-cloud-storage-v2:2.6.0-alpha:2.6.0-alpha -grpc-google-cloud-storage-v2:2.6.0-alpha:2.6.0-alpha -proto-google-cloud-storage-v2:2.6.0-alpha:2.6.0-alpha +google-cloud-storage:2.6.1:2.6.1 +gapic-google-cloud-storage-v2:2.6.1-alpha:2.6.1-alpha +grpc-google-cloud-storage-v2:2.6.1-alpha:2.6.1-alpha +proto-google-cloud-storage-v2:2.6.1-alpha:2.6.1-alpha