Skip to content

Commit 1d24c0d

Browse files
committed
fix: update bucket creation to set project as bucket.project
Creation of a bucket is modifying which field is used to specify the project a bucket is associated with. Changing from `parent` to `bucket.project`. This change updates our handling to use this new field. The existing `parent` is set to the sentinel value `projects/_` which was previously only implicitly found in the bucket name. Update testbench tag to v0.35.0 which includes the new field behavior. ApiaryConversions have been updated to track the project attribute when cross converting as the property `.x_project`; this value should avoid any possible collision if the field name project is supported in the future while the client is operating in this intervening time. If/when StorageObject receives its own project field we should switch to using it. Fix associated with b/254678990
1 parent baa7d19 commit 1d24c0d

File tree

6 files changed

+32
-5
lines changed

6 files changed

+32
-5
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.cloud.storage.Utils.ifNonNull;
2222
import static com.google.cloud.storage.Utils.lift;
2323
import static com.google.cloud.storage.Utils.nullableDateTimeCodec;
24+
import static com.google.cloud.storage.Utils.projectNameCodec;
2425
import static com.google.common.base.MoreObjects.firstNonNull;
2526

2627
import com.google.api.client.util.Data;
@@ -84,6 +85,10 @@
8485
@InternalApi
8586
final class ApiaryConversions {
8687
static final ApiaryConversions INSTANCE = new ApiaryConversions();
88+
// gRPC has a Bucket.project property that apiary doesn't have yet.
89+
// when converting from gRPC to apiary or vice-versa we want to preserve this property. Until
90+
// such a time as the apiary model has a project field, we manually apply it with this name.
91+
private static final String PROJECT_ID_FIELD_NAME = "x_project";
8792

8893
private final Codec<Entity, String> entityCodec =
8994
Codec.of(this::entityEncode, this::entityDecode);
@@ -323,6 +328,7 @@ private CustomerEncryption customerEncryptionDecode(StorageObject.CustomerEncryp
323328

324329
private Bucket bucketInfoEncode(BucketInfo from) {
325330
Bucket to = new Bucket();
331+
ifNonNull(from.getProject(), projectNameCodec::encode, p -> to.set(PROJECT_ID_FIELD_NAME, p));
326332
ifNonNull(from.getAcl(), toListOf(bucketAcl()::encode), to::setAcl);
327333
ifNonNull(from.getCors(), toListOf(cors()::encode), to::setCors);
328334
ifNonNull(from.getCreateTimeOffsetDateTime(), dateTimeCodec::encode, to::setTimeCreated);
@@ -395,6 +401,10 @@ private Bucket bucketInfoEncode(BucketInfo from) {
395401
@SuppressWarnings("deprecation")
396402
private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket from) {
397403
BucketInfo.Builder to = new BucketInfo.BuilderImpl(from.getName());
404+
ifNonNull(
405+
from.get(PROJECT_ID_FIELD_NAME),
406+
lift(String.class::cast).andThen(projectNameCodec::decode),
407+
to::setProject);
398408
ifNonNull(from.getAcl(), toListOf(bucketAcl()::decode), to::setAcl);
399409
ifNonNull(from.getCors(), toListOf(cors()::decode), to::setCors);
400410
ifNonNull(from.getDefaultObjectAcl(), toListOf(objectAcl()::decode), to::setDefaultAcl);

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ Codec<Policy, com.google.iam.v1.Policy> policyCodec() {
209209

210210
private BucketInfo bucketInfoDecode(Bucket from) {
211211
BucketInfo.Builder to = new BucketInfo.BuilderImpl(bucketNameCodec.decode(from.getName()));
212-
to.setProject(from.getProject());
212+
to.setProject(projectNameCodec.decode(from.getProject()));
213213
to.setGeneratedId(from.getBucketId());
214214
maybeDecodeRetentionPolicy(from, to);
215215
ifNonNull(from.getLocation(), to::setLocation);
@@ -302,6 +302,7 @@ private BucketInfo bucketInfoDecode(Bucket from) {
302302
private Bucket bucketInfoEncode(BucketInfo from) {
303303
Bucket.Builder to = Bucket.newBuilder();
304304
to.setName(bucketNameCodec.encode(from.getName()));
305+
ifNonNull(from.getProject(), projectNameCodec::encode, to::setProject);
305306
ifNonNull(from.getGeneratedId(), to::setBucketId);
306307
maybeEncodeRetentionPolicy(from, to);
307308
ifNonNull(from.getLocation(), to::setLocation);

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@
9999
import com.google.storage.v2.Object;
100100
import com.google.storage.v2.ObjectAccessControl;
101101
import com.google.storage.v2.ObjectChecksums;
102-
import com.google.storage.v2.ProjectName;
103102
import com.google.storage.v2.ReadObjectRequest;
104103
import com.google.storage.v2.RewriteObjectRequest;
105104
import com.google.storage.v2.RewriteResponse;
@@ -190,12 +189,15 @@ public Bucket create(BucketInfo bucketInfo, BucketTargetOption... options) {
190189
Opts<BucketTargetOpt> opts = Opts.unwrap(options).resolveFrom(bucketInfo).prepend(defaultOpts);
191190
GrpcCallContext grpcCallContext =
192191
opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault());
192+
if (bucketInfo.getProject() == null || bucketInfo.getProject().trim().isEmpty()) {
193+
bucketInfo = bucketInfo.toBuilder().setProject(getOptions().getProjectId()).build();
194+
}
193195
com.google.storage.v2.Bucket bucket = codecs.bucketInfo().encode(bucketInfo);
194196
CreateBucketRequest.Builder builder =
195197
CreateBucketRequest.newBuilder()
196198
.setBucket(bucket)
197199
.setBucketId(bucketInfo.getName())
198-
.setParent(ProjectName.format(getOptions().getProjectId()));
200+
.setParent("projects/_");
199201
CreateBucketRequest req = opts.createBucketsRequest().apply(builder).build();
200202
return Retrying.run(
201203
getOptions(),

google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/TestBench.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static final class Builder {
413413
private static final String DEFAULT_GRPC_BASE_URI = "http://localhost:9005";
414414
private static final String DEFAULT_IMAGE_NAME =
415415
"gcr.io/cloud-devrel-public-resources/storage-testbench";
416-
private static final String DEFAULT_IMAGE_TAG = "v0.33.0";
416+
private static final String DEFAULT_IMAGE_TAG = "v0.35.0";
417417
private static final String DEFAULT_CONTAINER_NAME = "default";
418418

419419
private boolean ignorePullError;

google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import static com.google.cloud.storage.PackagePrivateMethodWorkarounds.ifNonNull;
2020

21+
import com.google.cloud.storage.jqwik.StorageArbitraries.ProjectID;
2122
import com.google.storage.v2.Bucket;
2223
import com.google.storage.v2.BucketName;
24+
import com.google.storage.v2.ProjectName;
2325
import java.util.Collections;
2426
import java.util.Set;
2527
import javax.annotation.ParametersAreNonnullByDefault;
@@ -72,9 +74,15 @@ public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtyp
7274
StorageArbitraries.buckets().iamConfig().injectNull(0.5),
7375
StorageArbitraries.buckets().labels(),
7476
StorageArbitraries.etag())
77+
.as(Tuple::of),
78+
Combinators.combine(
79+
StorageArbitraries.projectID().map(ProjectID::toProjectName),
80+
StorageArbitraries
81+
.alnum() // ignored for now, tuples can't be a single element
82+
)
7583
.as(Tuple::of))
7684
.as(
77-
(t1, t2, t3) -> {
85+
(t1, t2, t3, t4) -> {
7886
Bucket.Builder b = Bucket.newBuilder();
7987
ifNonNull(t1.get1(), BucketName::getBucket, b::setBucketId);
8088
ifNonNull(t1.get2(), BucketName::toString, b::setName);
@@ -100,6 +108,7 @@ public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtyp
100108
ifNonNull(t3.get6(), b::setIamConfig);
101109
ifNonNull(t3.get7(), b::putAllLabels);
102110
ifNonNull(t3.get8(), b::setEtag);
111+
ifNonNull(t4.get1(), ProjectName::toString, b::setProject);
103112
// TODO: add CustomPlacementConfig
104113
return b.build();
105114
});

google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.google.storage.v2.ObjectAccessControl;
3838
import com.google.storage.v2.ObjectChecksums;
3939
import com.google.storage.v2.Owner;
40+
import com.google.storage.v2.ProjectName;
4041
import com.google.storage.v2.ProjectTeam;
4142
import com.google.type.Date;
4243
import java.math.BigInteger;
@@ -437,6 +438,10 @@ private ProjectID(String value) {
437438
public String get() {
438439
return value;
439440
}
441+
442+
public ProjectName toProjectName() {
443+
return ProjectName.of(value);
444+
}
440445
}
441446

442447
public static Objects objects() {

0 commit comments

Comments
 (0)