Skip to content

Commit affb14f

Browse files
committed
chore: plumb BlobSourceOptions into the request and grpc context for getBlobDescriptor
1 parent 09c426b commit affb14f

File tree

4 files changed

+146
-1
lines changed

4 files changed

+146
-1
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,7 @@ public ApiFuture<BlobDescriptor> getBlobDescriptor(BlobId id, BlobSourceOption..
15391539
}
15401540
BidiReadObjectRequest.Builder b = BidiReadObjectRequest.newBuilder();
15411541
b.setReadObjectSpec(spec);
1542+
opts.bidiReadObjectRequest().apply(b);
15421543
BidiReadObjectRequest req = b.build();
15431544

15441545
ZeroCopyBidiStreamingCallable<BidiReadObjectRequest, BidiReadObjectResponse> callable =

google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.google.iam.v1.GetIamPolicyRequest;
3838
import com.google.protobuf.ByteString;
3939
import com.google.protobuf.FieldMask;
40+
import com.google.storage.v2.BidiReadObjectRequest;
4041
import com.google.storage.v2.BidiWriteObjectRequest;
4142
import com.google.storage.v2.CommonObjectRequestParams;
4243
import com.google.storage.v2.ComposeObjectRequest;
@@ -151,6 +152,10 @@ default Mapper<ReadObjectRequest.Builder> readObject() {
151152
return Mapper.identity();
152153
}
153154

155+
default Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
156+
return Mapper.identity();
157+
}
158+
154159
default Mapper<GetObjectRequest.Builder> getObject() {
155160
return Mapper.identity();
156161
}
@@ -656,6 +661,15 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
656661
};
657662
}
658663

664+
@Override
665+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
666+
return b -> {
667+
customerSuppliedKey(
668+
b.getReadObjectSpecBuilder().getCommonObjectRequestParamsBuilder(), val);
669+
return b;
670+
};
671+
}
672+
659673
@Override
660674
public Mapper<GetObjectRequest.Builder> getObject() {
661675
return b -> {
@@ -896,6 +910,15 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
896910
return b -> b.setReadMask(FieldMask.newBuilder().addAllPaths(getPaths()).build());
897911
}
898912

913+
@Override
914+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
915+
return b -> {
916+
b.getReadObjectSpecBuilder()
917+
.setReadMask(FieldMask.newBuilder().addAllPaths(getPaths()).build());
918+
return b;
919+
};
920+
}
921+
899922
@Override
900923
public Mapper<UpdateObjectRequest.Builder> updateObject() {
901924
return b -> b.setUpdateMask(FieldMask.newBuilder().addAllPaths(getPaths()).build());
@@ -1094,6 +1117,14 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
10941117
return b -> b.setIfGenerationMatch(val);
10951118
}
10961119

1120+
@Override
1121+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
1122+
return b -> {
1123+
b.getReadObjectSpecBuilder().setIfGenerationMatch(val);
1124+
return b;
1125+
};
1126+
}
1127+
10971128
@Override
10981129
public Mapper<GetObjectRequest.Builder> getObject() {
10991130
return b -> b.setIfGenerationMatch(val);
@@ -1168,6 +1199,14 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
11681199
return b -> b.setIfGenerationNotMatch(val);
11691200
}
11701201

1202+
@Override
1203+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
1204+
return b -> {
1205+
b.getReadObjectSpecBuilder().setIfGenerationNotMatch(val);
1206+
return b;
1207+
};
1208+
}
1209+
11711210
@Override
11721211
public Mapper<GetObjectRequest.Builder> getObject() {
11731212
return b -> b.setIfGenerationNotMatch(val);
@@ -1343,6 +1382,14 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
13431382
return b -> b.setIfMetagenerationMatch(val);
13441383
}
13451384

1385+
@Override
1386+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
1387+
return b -> {
1388+
b.getReadObjectSpecBuilder().setIfMetagenerationMatch(val);
1389+
return b;
1390+
};
1391+
}
1392+
13461393
@Override
13471394
public Mapper<GetObjectRequest.Builder> getObject() {
13481395
return b -> b.setIfMetagenerationMatch(val);
@@ -1441,6 +1488,14 @@ public Mapper<ReadObjectRequest.Builder> readObject() {
14411488
return b -> b.setIfMetagenerationNotMatch(val);
14421489
}
14431490

1491+
@Override
1492+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObject() {
1493+
return b -> {
1494+
b.getReadObjectSpecBuilder().setIfMetagenerationNotMatch(val);
1495+
return b;
1496+
};
1497+
}
1498+
14441499
@Override
14451500
public Mapper<GetObjectRequest.Builder> getObject() {
14461501
return b -> b.setIfMetagenerationNotMatch(val);
@@ -2667,6 +2722,10 @@ Mapper<ReadObjectRequest.Builder> readObjectRequest() {
26672722
return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::readObject);
26682723
}
26692724

2725+
public Mapper<BidiReadObjectRequest.Builder> bidiReadObjectRequest() {
2726+
return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::bidiReadObject);
2727+
}
2728+
26702729
Mapper<ListObjectsRequest.Builder> listObjectsRequest() {
26712730
return fuseMappers(ObjectListOpt.class, ObjectListOpt::listObjects);
26722731
}

google-cloud-storage/src/test/java/com/google/cloud/storage/ITBlobDescriptorFakeTest.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@
3434
import com.google.cloud.storage.Storage.BlobSourceOption;
3535
import com.google.cloud.storage.it.ChecksummedTestContent;
3636
import com.google.cloud.storage.it.GrpcPlainRequestLoggingInterceptor;
37+
import com.google.cloud.storage.it.GrpcRequestAuditing;
38+
import com.google.common.collect.ImmutableList;
3739
import com.google.common.collect.ImmutableMap;
3840
import com.google.common.collect.Maps;
41+
import com.google.common.hash.Hashing;
42+
import com.google.common.io.BaseEncoding;
3943
import com.google.protobuf.Any;
4044
import com.google.protobuf.ByteString;
4145
import com.google.storage.v2.BidiReadHandle;
@@ -46,6 +50,7 @@
4650
import com.google.storage.v2.BidiReadObjectSpec;
4751
import com.google.storage.v2.BucketName;
4852
import com.google.storage.v2.ChecksummedData;
53+
import com.google.storage.v2.CommonObjectRequestParams;
4954
import com.google.storage.v2.Object;
5055
import com.google.storage.v2.ObjectRangeData;
5156
import com.google.storage.v2.ReadRange;
@@ -58,6 +63,7 @@
5863
import io.grpc.protobuf.ProtoUtils;
5964
import io.grpc.stub.StreamObserver;
6065
import java.nio.ByteBuffer;
66+
import java.security.Key;
6167
import java.util.Arrays;
6268
import java.util.Map;
6369
import java.util.UUID;
@@ -66,6 +72,7 @@
6672
import java.util.concurrent.atomic.AtomicInteger;
6773
import java.util.function.Consumer;
6874
import java.util.stream.Collectors;
75+
import javax.crypto.spec.SecretKeySpec;
6976
import org.junit.Test;
7077

7178
public final class ITBlobDescriptorFakeTest {
@@ -93,6 +100,10 @@ public final class ITBlobDescriptorFakeTest {
93100
private static final BidiReadObjectResponse RES_OPEN =
94101
BidiReadObjectResponse.newBuilder().setMetadata(METADATA).build();
95102
private static final byte[] ALL_OBJECT_BYTES = DataGenerator.base64Characters().genBytes(64);
103+
private static final Metadata.Key<String> X_GOOG_REQUEST_PARAMS =
104+
Metadata.Key.of("x-goog-request-params", Metadata.ASCII_STRING_MARSHALLER);
105+
private static final Metadata.Key<String> X_GOOG_USER_PROJECT =
106+
Metadata.Key.of("x-goog-user-project", Metadata.ASCII_STRING_MARSHALLER);
96107

97108
/**
98109
*
@@ -794,6 +805,74 @@ public void validateReadRemovedFromStateWhenFailed() throws Exception {
794805
}
795806
}
796807

808+
@Test
809+
public void requestOptionsShouldBePresentInRequest() throws Exception {
810+
811+
String keyB64 = "JVzfVl8NLD9FjedFuStegjRfES5ll5zc59CIXw572OA=";
812+
Key key = new SecretKeySpec(BaseEncoding.base64().decode(keyB64), "AES256");
813+
byte[] keySha256 = Hashing.sha256().hashBytes(key.getEncoded()).asBytes();
814+
BidiReadObjectRequest reqOpen =
815+
BidiReadObjectRequest.newBuilder()
816+
.setReadObjectSpec(
817+
BidiReadObjectSpec.newBuilder()
818+
.setBucket(METADATA.getBucket())
819+
.setObject(METADATA.getName())
820+
.setIfGenerationMatch(1)
821+
.setIfGenerationNotMatch(2)
822+
.setIfMetagenerationMatch(3)
823+
.setIfMetagenerationNotMatch(4)
824+
.setCommonObjectRequestParams(
825+
CommonObjectRequestParams.newBuilder()
826+
.setEncryptionAlgorithm("AES256")
827+
.setEncryptionKeyBytes(ByteString.copyFrom(key.getEncoded()))
828+
.setEncryptionKeySha256Bytes(ByteString.copyFrom(keySha256))))
829+
.build();
830+
BidiReadObjectResponse resOpen =
831+
BidiReadObjectResponse.newBuilder().setMetadata(METADATA).build();
832+
833+
FakeStorage fake = FakeStorage.from(ImmutableMap.of(reqOpen, resOpen));
834+
835+
GrpcRequestAuditing requestAuditing = new GrpcRequestAuditing();
836+
try (FakeServer fakeServer = FakeServer.of(fake);
837+
Storage storage =
838+
fakeServer
839+
.getGrpcStorageOptions()
840+
.toBuilder()
841+
.setRetrySettings(RetrySettings.newBuilder().setMaxAttempts(1).build())
842+
.setGrpcInterceptorProvider(
843+
() ->
844+
ImmutableList.of(
845+
requestAuditing, GrpcPlainRequestLoggingInterceptor.getInstance()))
846+
.build()
847+
.getService()) {
848+
849+
BlobId id = BlobId.of("b", "o");
850+
ApiFuture<BlobDescriptor> futureObjectDescriptor =
851+
storage.getBlobDescriptor(
852+
id,
853+
BlobSourceOption.generationMatch(1),
854+
BlobSourceOption.generationNotMatch(2),
855+
BlobSourceOption.metagenerationMatch(3),
856+
BlobSourceOption.metagenerationNotMatch(4),
857+
BlobSourceOption.decryptionKey(key),
858+
BlobSourceOption.userProject("my-awesome-project"));
859+
860+
try (BlobDescriptor bd = futureObjectDescriptor.get(5, TimeUnit.SECONDS)) {
861+
// by the time we reach here the test has already passed/failed
862+
assertAll(
863+
() -> assertThat(bd).isNotNull(),
864+
() ->
865+
requestAuditing
866+
.assertRequestHeader(X_GOOG_REQUEST_PARAMS)
867+
.contains("bucket=" + METADATA.getBucket()),
868+
() ->
869+
requestAuditing
870+
.assertRequestHeader(X_GOOG_USER_PROJECT)
871+
.contains("my-awesome-project"));
872+
}
873+
}
874+
}
875+
797876
private static void runTestAgainstFakeServer(
798877
FakeStorage fakeStorage, RangeSpec range, ChecksummedTestContent expected) throws Exception {
799878

google-cloud-storage/src/test/java/com/google/cloud/storage/it/GrpcRequestAuditing.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.common.truth.Truth.assertWithMessage;
2020

21+
import com.google.api.gax.grpc.GrpcInterceptorProvider;
2122
import com.google.common.collect.ImmutableList;
2223
import com.google.common.truth.IterableSubject;
2324
import io.grpc.Attributes;
@@ -38,7 +39,7 @@
3839
import java.util.stream.Stream;
3940
import org.checkerframework.checker.nullness.qual.NonNull;
4041

41-
public final class GrpcRequestAuditing implements ClientInterceptor, AssertRequestHeaders {
42+
public final class GrpcRequestAuditing implements ClientInterceptor, AssertRequestHeaders, GrpcInterceptorProvider {
4243

4344
private final List<Metadata> requestHeaders;
4445

@@ -85,6 +86,11 @@ public <T> IterableSubject assertRequestHeader(Metadata.Key<T> key) {
8586
return assertWithMessage(String.format(Locale.US, "Headers %s", key.name())).that(actual);
8687
}
8788

89+
@Override
90+
public List<ClientInterceptor> getInterceptors() {
91+
return ImmutableList.of(this);
92+
}
93+
8894
private final class Factory extends ClientStreamTracer.Factory {
8995
@Override
9096
public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {

0 commit comments

Comments
 (0)