allowedIpCidrRanges) {
+ this.network = network;
+ this.allowedIpCidrRanges = allowedIpCidrRanges;
+ }
+
+ /**
+ * Name of the network.
+ *
+ * Format: `projects/PROJECT_ID/global/networks/NETWORK_NAME`
+ *
+ * @since 2.54.0
+ * @see Builder#setNetwork(String)
+ */
+ public @Nullable String getNetwork() {
+ return network;
+ }
+
+ /**
+ * Optional. The list of public or private IPv4 and IPv6 CIDR ranges that can access the
+ * bucket. In the CIDR IP address block, the specified IP address must be properly truncated,
+ * meaning all the host bits must be zero or else the input is considered malformed. For
+ * example, `192.0.2.0/24` is accepted but `192.0.2.1/24` is not. Similarly, for IPv6,
+ * `2001:db8::/32` is accepted whereas `2001:db8::1/32` is not.
+ *
+ * @since 2.54.0
+ * @see Builder#setAllowedIpCidrRanges(List)
+ */
+ public @Nullable List getAllowedIpCidrRanges() {
+ return allowedIpCidrRanges;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof VpcNetworkSource)) {
+ return false;
+ }
+ VpcNetworkSource that = (VpcNetworkSource) o;
+ return Objects.equals(network, that.network)
+ && Objects.equals(allowedIpCidrRanges, that.allowedIpCidrRanges);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(network, allowedIpCidrRanges);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("network", network)
+ .add("allowedIpCidrRanges", allowedIpCidrRanges)
+ .toString();
+ }
+
+ /**
+ * @since 2.54.0
+ */
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ /**
+ * @since 2.54.0
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * @since 2.54.0
+ */
+ public static final class Builder {
+ private @Nullable String network;
+ private @Nullable List allowedIpCidrRanges;
+
+ private Builder() {}
+
+ public Builder(VpcNetworkSource vpcNetworksource) {
+ this.network = vpcNetworksource.network;
+ this.allowedIpCidrRanges = vpcNetworksource.allowedIpCidrRanges;
+ }
+
+ /**
+ * Name of the network.
+ *
+ * Format: `projects/PROJECT_ID/global/networks/NETWORK_NAME`
+ *
+ * @since 2.54.0
+ * @see VpcNetworkSource#getNetwork()
+ */
+ public Builder setNetwork(@Nullable String network) {
+ this.network = network;
+ return this;
+ }
+
+ /**
+ * Optional. The list of public or private IPv4 and IPv6 CIDR ranges that can access the
+ * bucket. In the CIDR IP address block, the specified IP address must be properly
+ * truncated, meaning all the host bits must be zero or else the input is considered
+ * malformed. For example, `192.0.2.0/24` is accepted but `192.0.2.1/24` is not. Similarly,
+ * for IPv6, `2001:db8::/32` is accepted whereas `2001:db8::1/32` is not.
+ *
+ * @since 2.54.0
+ * @see VpcNetworkSource#getAllowedIpCidrRanges()
+ */
+ public Builder setAllowedIpCidrRanges(@Nullable List allowedIpCidrRanges) {
+ this.allowedIpCidrRanges = allowedIpCidrRanges;
+ return this;
+ }
+
+ /**
+ * @since 2.54.0
+ */
+ public VpcNetworkSource build() {
+ return new VpcNetworkSource(network, allowedIpCidrRanges);
+ }
+ }
+ }
+ }
+
/** Builder for {@code BucketInfo}. */
public abstract static class Builder {
Builder() {}
@@ -1857,6 +2285,11 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) {
public abstract Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy);
+ /**
+ * @since 2.54.0
+ */
+ public abstract Builder setIpFilter(IpFilter ipFilter);
+
/** Creates a {@code BucketInfo} object. */
public abstract BucketInfo build();
@@ -1919,6 +2352,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) {
abstract Builder clearLogging();
abstract Builder clearCustomPlacementConfig();
+
+ abstract Builder clearIpFilter();
}
static final class BuilderImpl extends Builder {
@@ -1958,6 +2393,7 @@ static final class BuilderImpl extends Builder {
private SoftDeletePolicy softDeletePolicy;
private HierarchicalNamespace hierarchicalNamespace;
+ private IpFilter ipFilter;
private final ImmutableSet.Builder modifiedFields = ImmutableSet.builder();
BuilderImpl(String name) {
@@ -1999,6 +2435,7 @@ static final class BuilderImpl extends Builder {
objectRetention = bucketInfo.objectRetention;
softDeletePolicy = bucketInfo.softDeletePolicy;
hierarchicalNamespace = bucketInfo.hierarchicalNamespace;
+ ipFilter = bucketInfo.ipFilter;
}
@Override
@@ -2404,6 +2841,15 @@ Builder setLocationType(String locationType) {
return this;
}
+ @Override
+ public Builder setIpFilter(IpFilter ipFilter) {
+ if (!Objects.equals(this.ipFilter, ipFilter)) {
+ modifiedFields.add(BucketField.IP_FILTER);
+ }
+ this.ipFilter = ipFilter;
+ return this;
+ }
+
@Override
public BucketInfo build() {
checkNotNull(name);
@@ -2590,6 +3036,12 @@ BuilderImpl clearCustomPlacementConfig() {
return this;
}
+ @Override
+ BuilderImpl clearIpFilter() {
+ this.ipFilter = null;
+ return this;
+ }
+
private Builder clearDeleteLifecycleRules() {
if (lifecycleRules != null && !lifecycleRules.isEmpty()) {
ImmutableList nonDeleteRules =
@@ -2638,6 +3090,7 @@ private Builder clearDeleteLifecycleRules() {
objectRetention = builder.objectRetention;
softDeletePolicy = builder.softDeletePolicy;
hierarchicalNamespace = builder.hierarchicalNamespace;
+ ipFilter = builder.ipFilter;
modifiedFields = builder.modifiedFields.build();
}
@@ -2989,6 +3442,13 @@ public HierarchicalNamespace getHierarchicalNamespace() {
return hierarchicalNamespace;
}
+ /**
+ * @since 2.54.0
+ */
+ public @Nullable IpFilter getIpFilter() {
+ return ipFilter;
+ }
+
/** Returns a builder for the current bucket. */
public Builder toBuilder() {
return new BuilderImpl(this);
@@ -3030,7 +3490,8 @@ public int hashCode() {
softDeletePolicy,
customPlacementConfig,
hierarchicalNamespace,
- logging);
+ logging,
+ ipFilter);
}
@Override
@@ -3075,7 +3536,8 @@ public boolean equals(Object o) {
&& Objects.equals(objectRetention, that.objectRetention)
&& Objects.equals(softDeletePolicy, that.softDeletePolicy)
&& Objects.equals(hierarchicalNamespace, that.hierarchicalNamespace)
- && Objects.equals(logging, that.logging);
+ && Objects.equals(logging, that.logging)
+ && Objects.equals(ipFilter, that.ipFilter);
}
@Override
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
index 4d9d5e31d..a530c3546 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
@@ -16,6 +16,7 @@
package com.google.cloud.storage;
+import static com.google.cloud.storage.Storage.BucketField.IP_FILTER;
import static com.google.cloud.storage.Storage.BucketField.SOFT_DELETE_POLICY;
import static com.google.cloud.storage.Utils.bucketNameCodec;
import static com.google.cloud.storage.Utils.ifNonNull;
@@ -30,6 +31,7 @@
import com.google.cloud.storage.Acl.Role;
import com.google.cloud.storage.BlobInfo.CustomerEncryption;
import com.google.cloud.storage.BucketInfo.CustomPlacementConfig;
+import com.google.cloud.storage.BucketInfo.IpFilter;
import com.google.cloud.storage.BucketInfo.LifecycleRule;
import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction;
import com.google.cloud.storage.BucketInfo.Logging;
@@ -44,6 +46,8 @@
import com.google.protobuf.Timestamp;
import com.google.storage.v2.Bucket;
import com.google.storage.v2.Bucket.Billing;
+import com.google.storage.v2.Bucket.IpFilter.PublicNetworkSource;
+import com.google.storage.v2.Bucket.IpFilter.VpcNetworkSource;
import com.google.storage.v2.Bucket.Website;
import com.google.storage.v2.BucketAccessControl;
import com.google.storage.v2.CryptoKeyName;
@@ -107,6 +111,14 @@ final class GrpcConversions {
hierarchicalNamespaceCodec =
Codec.of(this::hierarchicalNamespaceEncode, this::hierarchicalNamespaceDecode);
+ private final Codec ipFilterCodec =
+ Codec.of(this::ipFilterEncode, this::ipFilterDecode);
+ private final Codec
+ publicNetworkSourceCodec =
+ Codec.of(this::publicNetworkSourceEncode, this::publicNetworkSourceDecode);
+ private final Codec
+ vpcNetworkSourceCodec = Codec.of(this::vpcNetworkSourceEncode, this::vpcNetworkSourceDecode);
+
private final Codec byteStringB64StringCodec =
Codec.of(
bs -> Base64.getEncoder().encodeToString(bs.toByteArray()),
@@ -296,7 +308,9 @@ private BucketInfo bucketInfoDecode(Bucket from) {
to.setHierarchicalNamespace(
hierarchicalNamespaceCodec.decode(from.getHierarchicalNamespace()));
}
- // TODO(frankyn): Add SelfLink when the field is available
+ if (from.hasIpFilter()) {
+ to.setIpFilter(ipFilterCodec.decode(from.getIpFilter()));
+ }
if (!from.getEtag().isEmpty()) {
to.setEtag(from.getEtag());
}
@@ -390,7 +404,10 @@ private Bucket bucketInfoEncode(BucketInfo from) {
from.getHierarchicalNamespace(),
hierarchicalNamespaceCodec::encode,
to::setHierarchicalNamespace);
- // TODO(frankyn): Add SelfLink when the field is available
+ ifNonNull(from.getIpFilter(), ipFilterCodec::encode, to::setIpFilter);
+ if (from.getModifiedFields().contains(IP_FILTER) && from.getIpFilter() == null) {
+ to.clearIpFilter();
+ }
ifNonNull(from.getEtag(), to::setEtag);
return to.build();
}
@@ -1037,8 +1054,68 @@ private String removeKmsVersion(String from) {
return from;
}
- private static T todo() {
- throw new IllegalStateException("Not yet implemented");
+ private Bucket.IpFilter ipFilterEncode(IpFilter from) {
+ Bucket.IpFilter.Builder to = Bucket.IpFilter.newBuilder();
+ ifNonNull(from.getMode(), to::setMode);
+ ifNonNull(
+ from.getPublicNetworkSource(),
+ publicNetworkSourceCodec::encode,
+ to::setPublicNetworkSource);
+ ifNonNull(
+ from.getVpcNetworkSources(),
+ toImmutableListOf(vpcNetworkSourceCodec::encode),
+ to::addAllVpcNetworkSources);
+ ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs);
+ ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess);
+ return to.build();
+ }
+
+ private IpFilter ipFilterDecode(Bucket.IpFilter from) {
+ IpFilter.Builder to = IpFilter.newBuilder();
+ if (!from.getMode().isEmpty()) {
+ to.setMode(from.getMode());
+ }
+ ifNonNull(
+ from.getPublicNetworkSource(),
+ publicNetworkSourceCodec::decode,
+ to::setPublicNetworkSource);
+ ifNonNull(
+ from.getVpcNetworkSourcesList(),
+ toImmutableListOf(vpcNetworkSourceCodec::decode),
+ to::setVpcNetworkSources);
+ ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs);
+ if (from.hasAllowAllServiceAgentAccess()) {
+ to.setAllowAllServiceAgentAccess(from.getAllowAllServiceAgentAccess());
+ }
+ return to.build();
+ }
+
+ private PublicNetworkSource publicNetworkSourceEncode(IpFilter.PublicNetworkSource from) {
+ PublicNetworkSource.Builder to = PublicNetworkSource.newBuilder();
+ ifNonNull(from.getAllowedIpCidrRanges(), to::addAllAllowedIpCidrRanges);
+ return to.build();
+ }
+
+ private IpFilter.PublicNetworkSource publicNetworkSourceDecode(PublicNetworkSource from) {
+ return IpFilter.PublicNetworkSource.of(from.getAllowedIpCidrRangesList());
+ }
+
+ private VpcNetworkSource vpcNetworkSourceEncode(IpFilter.VpcNetworkSource from) {
+ VpcNetworkSource.Builder to = VpcNetworkSource.newBuilder();
+ ifNonNull(from.getNetwork(), to::setNetwork);
+ ifNonNull(from.getAllowedIpCidrRanges(), to::addAllAllowedIpCidrRanges);
+ return to.build();
+ }
+
+ private IpFilter.VpcNetworkSource vpcNetworkSourceDecode(VpcNetworkSource from) {
+ IpFilter.VpcNetworkSource.Builder to = IpFilter.VpcNetworkSource.newBuilder();
+ if (from.hasNetwork()) {
+ to.setNetwork(from.getNetwork());
+ }
+ if (!from.getAllowedIpCidrRangesList().isEmpty()) {
+ to.setAllowedIpCidrRanges(from.getAllowedIpCidrRangesList());
+ }
+ return to.build();
}
/**
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java
index 7f9da1f58..c79fa288e 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java
@@ -16,6 +16,7 @@
package com.google.cloud.storage;
+import static com.google.cloud.storage.Storage.BucketField.IP_FILTER;
import static com.google.cloud.storage.Storage.BucketField.SOFT_DELETE_POLICY;
import static com.google.cloud.storage.Utils.dateTimeCodec;
import static com.google.cloud.storage.Utils.durationSecondsCodec;
@@ -31,6 +32,7 @@
import com.google.api.services.storage.model.Bucket.Billing;
import com.google.api.services.storage.model.Bucket.Encryption;
import com.google.api.services.storage.model.Bucket.IamConfiguration.UniformBucketLevelAccess;
+import com.google.api.services.storage.model.Bucket.IpFilter.VpcNetworkSources;
import com.google.api.services.storage.model.Bucket.Lifecycle;
import com.google.api.services.storage.model.Bucket.Lifecycle.Rule;
import com.google.api.services.storage.model.Bucket.Lifecycle.Rule.Action;
@@ -57,6 +59,7 @@
import com.google.cloud.storage.BucketInfo.Autoclass;
import com.google.cloud.storage.BucketInfo.CustomPlacementConfig;
import com.google.cloud.storage.BucketInfo.IamConfiguration;
+import com.google.cloud.storage.BucketInfo.IpFilter;
import com.google.cloud.storage.BucketInfo.LifecycleRule;
import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction;
import com.google.cloud.storage.BucketInfo.LifecycleRule.DeleteLifecycleAction;
@@ -149,6 +152,14 @@ final class JsonConversions {
private final Codec
iamConditionCodec = Codec.of(this::conditionEncode, this::conditionDecode);
+ private final Codec ipFilterCodec =
+ Codec.of(this::ipFilterEncode, this::ipFilterDecode);
+ private final Codec
+ publicNetworkSourceCodec =
+ Codec.of(this::publicNetworkSourceEncode, this::publicNetworkSourceDecode);
+ private final Codec
+ vpcNetworkSourceCodec = Codec.of(this::vpcNetworkSourceEncode, this::vpcNetworkSourceDecode);
+
private JsonConversions() {}
Codec entity() {
@@ -466,6 +477,10 @@ private Bucket bucketInfoEncode(BucketInfo from) {
from.getHierarchicalNamespace(),
this::hierarchicalNamespaceEncode,
to::setHierarchicalNamespace);
+ ifNonNull(from.getIpFilter(), ipFilterCodec::encode, to::setIpFilter);
+ if (from.getModifiedFields().contains(IP_FILTER) && from.getIpFilter() == null) {
+ to.setIpFilter(Data.nullOf(Bucket.IpFilter.class));
+ }
return to;
}
@@ -519,6 +534,7 @@ private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket
to::setHierarchicalNamespace);
ifNonNull(from.getObjectRetention(), this::objectRetentionDecode, to::setObjectRetention);
ifNonNull(from.getSoftDeletePolicy(), this::softDeletePolicyDecode, to::setSoftDeletePolicy);
+ ifNonNull(from.getIpFilter(), ipFilterCodec::decode, to::setIpFilter);
return to.build();
}
@@ -1006,6 +1022,64 @@ private CustomPlacementConfig customPlacementConfigDecode(Bucket.CustomPlacement
return CustomPlacementConfig.newBuilder().setDataLocations(from.getDataLocations()).build();
}
+ private Bucket.IpFilter ipFilterEncode(IpFilter from) {
+ Bucket.IpFilter to = new Bucket.IpFilter();
+ ifNonNull(from.getMode(), to::setMode);
+ ifNonNull(
+ from.getPublicNetworkSource(),
+ publicNetworkSourceCodec::encode,
+ to::setPublicNetworkSource);
+ ifNonNull(
+ from.getVpcNetworkSources(),
+ toListOf(vpcNetworkSourceCodec::encode),
+ to::setVpcNetworkSources);
+ ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs);
+ ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess);
+ return to;
+ }
+
+ private IpFilter ipFilterDecode(Bucket.IpFilter from) {
+ IpFilter.Builder to = IpFilter.newBuilder();
+ ifNonNull(from.getMode(), to::setMode);
+ ifNonNull(
+ from.getPublicNetworkSource(),
+ publicNetworkSourceCodec::decode,
+ to::setPublicNetworkSource);
+ ifNonNull(
+ from.getVpcNetworkSources(),
+ toListOf(vpcNetworkSourceCodec::decode),
+ to::setVpcNetworkSources);
+ ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs);
+ ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess);
+ return to.build();
+ }
+
+ private Bucket.IpFilter.PublicNetworkSource publicNetworkSourceEncode(
+ IpFilter.PublicNetworkSource from) {
+ Bucket.IpFilter.PublicNetworkSource to = new Bucket.IpFilter.PublicNetworkSource();
+ ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges);
+ return to;
+ }
+
+ private IpFilter.PublicNetworkSource publicNetworkSourceDecode(
+ Bucket.IpFilter.PublicNetworkSource from) {
+ return IpFilter.PublicNetworkSource.of(from.getAllowedIpCidrRanges());
+ }
+
+ private Bucket.IpFilter.VpcNetworkSources vpcNetworkSourceEncode(IpFilter.VpcNetworkSource from) {
+ VpcNetworkSources to = new VpcNetworkSources();
+ ifNonNull(from.getNetwork(), to::setNetwork);
+ ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges);
+ return to;
+ }
+
+ private IpFilter.VpcNetworkSource vpcNetworkSourceDecode(Bucket.IpFilter.VpcNetworkSources from) {
+ IpFilter.VpcNetworkSource.Builder to = IpFilter.VpcNetworkSource.newBuilder();
+ ifNonNull(from.getNetwork(), to::setNetwork);
+ ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges);
+ return to.build();
+ }
+
private static void maybeEncodeRetentionPolicy(BucketInfo from, Bucket to) {
if (from.getRetentionPeriodDuration() != null
|| from.retentionPolicyIsLocked() != null
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
index d2c38763e..61597307f 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java
@@ -194,7 +194,13 @@ enum BucketField implements FieldSelector, NamedField {
com.google.api.services.storage.model.Bucket.SoftDeletePolicy.class),
@TransportCompatibility({Transport.HTTP, Transport.GRPC})
- PROJECT("projectNumber", "project", BigInteger.class);
+ PROJECT("projectNumber", "project", BigInteger.class),
+ /**
+ * @since 2.54.0
+ */
+ @TransportCompatibility({Transport.HTTP, Transport.GRPC})
+ IP_FILTER("ipFilter", "ip_filter", com.google.api.services.storage.model.Bucket.IpFilter.class),
+ ;
static final List REQUIRED_FIELDS = ImmutableList.of(NAME);
private static final Map JSON_FIELD_NAME_INDEX;
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java
index 77cb1344a..29444ad13 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java
@@ -1084,6 +1084,7 @@ private Set getPaths() {
BucketField.IAMCONFIGURATION.getGrpcName(),
BucketInfo.Builder::clearIamConfiguration)
.put(BucketField.ID.getGrpcName(), BucketInfo.Builder::clearGeneratedId)
+ .put(BucketField.IP_FILTER.getGrpcName(), BucketInfo.Builder::clearIpFilter)
.put(BucketField.LABELS.getGrpcName(), BucketInfo.Builder::clearLabels)
.put(BucketField.LIFECYCLE.getGrpcName(), BucketInfo.Builder::clearLifecycleRules)
.put(BucketField.LOCATION.getGrpcName(), BucketInfo.Builder::clearLocation)
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java
index 36991f1b8..cb9b5515c 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java
@@ -115,6 +115,7 @@ public ImmutableList> parameters() {
new Args<>(BucketField.ETAG, LazyAssertion.equal()),
new Args<>(BucketField.IAMCONFIGURATION, LazyAssertion.equal()),
new Args<>(BucketField.ID, LazyAssertion.equal()),
+ new Args<>(BucketField.IP_FILTER, LazyAssertion.equal()),
new Args<>(BucketField.LABELS, LazyAssertion.equal()),
new Args<>(BucketField.LIFECYCLE, LazyAssertion.equal()),
new Args<>(BucketField.LOCATION, LazyAssertion.equal()),
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java
index 905fe5478..e30fc3125 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java
@@ -61,6 +61,7 @@
import com.google.common.collect.ImmutableSet;
import java.util.Locale;
import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Function;
import org.junit.Before;
import org.junit.Test;
@@ -298,7 +299,7 @@ public void storage_BucketGetOption_userProject_String() {
@Test
public void storage_BucketGetOption_fields_BucketField() {
Set expected =
- ImmutableSet.of(
+ treeSet(
"acl",
"autoclass",
"billing",
@@ -310,6 +311,7 @@ public void storage_BucketGetOption_fields_BucketField() {
"etag",
"iamConfiguration",
"id",
+ "ipFilter",
"labels",
"lifecycle",
"location",
@@ -705,7 +707,7 @@ public void storage_BlobGetOption_metagenerationNotMatch_long() {
@Test
public void storage_BlobGetOption_fields_BlobField() {
Set expected =
- ImmutableSet.of(
+ treeSet(
"acl",
"bucket",
"cacheControl",
@@ -790,7 +792,7 @@ public void storage_BucketListOption_userProject_String() {
@Test
public void storage_BucketListOption_fields_BucketField() {
Set expected =
- ImmutableSet.of(
+ treeSet(
"nextPageToken",
"items/acl",
"items/autoclass",
@@ -803,6 +805,7 @@ public void storage_BucketListOption_fields_BucketField() {
"items/etag",
"items/iamConfiguration",
"items/id",
+ "items/ipFilter",
"items/labels",
"items/lifecycle",
"items/location",
@@ -883,7 +886,7 @@ public void storage_BlobListOption_versions_boolean() {
@Test
public void storage_BlobListOption_fields_BlobField() {
Set expected =
- ImmutableSet.of(
+ treeSet(
"nextPageToken",
"prefixes",
"items/acl",
@@ -1194,6 +1197,15 @@ private static String objectName() {
}
private static Function> splitOnCommaToSet() {
- return s -> ImmutableSet.copyOf(s.split(","));
+ return s -> treeSet(s.split(","));
+ }
+
+ /**
+ * Util method to make a TreeSet easily. This makes failed assertions easier to read by sorting
+ * the values.
+ */
+ @SafeVarargs
+ private static > Set treeSet(T... ts) {
+ return new TreeSet<>(ImmutableSet.copyOf(ts));
}
}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java
index 1839c32b4..9b71a59ac 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java
@@ -77,9 +77,7 @@ public Set> provideFor(TypeUsage targetType, SubtypeProvider subtyp
.as(Tuple::of),
Combinators.combine(
StorageArbitraries.projectNumber().map(ProjectNumber::toProjectName),
- StorageArbitraries
- .alnum() // ignored for now, tuples can't be a single element
- )
+ StorageArbitraries.buckets().ipFilter().injectNull(0.75))
.as(Tuple::of))
.as(
(t1, t2, t3, t4) -> {
@@ -109,6 +107,7 @@ public Set> provideFor(TypeUsage targetType, SubtypeProvider subtyp
ifNonNull(t3.get7(), b::putAllLabels);
ifNonNull(t3.get8(), b::setEtag);
ifNonNull(t4.get1(), ProjectName::toString, b::setProject);
+ ifNonNull(t4.get2(), b::setIpFilter);
// TODO: add CustomPlacementConfig
return b.build();
});
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java
index f5ee93ce0..0b6e21d98 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java
@@ -26,6 +26,9 @@
import com.google.storage.v2.Bucket;
import com.google.storage.v2.Bucket.Billing;
import com.google.storage.v2.Bucket.Encryption;
+import com.google.storage.v2.Bucket.IpFilter;
+import com.google.storage.v2.Bucket.IpFilter.PublicNetworkSource;
+import com.google.storage.v2.Bucket.IpFilter.VpcNetworkSource;
import com.google.storage.v2.Bucket.Lifecycle.Rule.Condition;
import com.google.storage.v2.Bucket.Logging;
import com.google.storage.v2.Bucket.RetentionPolicy;
@@ -58,6 +61,7 @@
import net.jqwik.api.providers.TypeUsage;
import net.jqwik.time.api.DateTimes;
import net.jqwik.web.api.Web;
+import org.checkerframework.checker.nullness.qual.Nullable;
public final class StorageArbitraries {
@@ -172,6 +176,19 @@ public static Arbitrary etag() {
.edgeCases(config -> config.add(""));
}
+ /** Arbitrary of ipv4 and ipv6 cidr ranges */
+ public static Arbitrary cidr() {
+ return Arbitraries.oneOf(cidrIpv4(), cidrIpv6());
+ }
+
+ public static Arbitrary cidrIpv4() {
+ return Arbitraries.of("182.0.2.0/24");
+ }
+
+ public static Arbitrary cidrIpv6() {
+ return Arbitraries.of("2001:db8::/32");
+ }
+
public static final class Buckets {
private static final Buckets INSTANCE = new Buckets();
@@ -429,6 +446,66 @@ public Arbitrary locationType() {
public Arbitrary