Skip to content

Commit e30896e

Browse files
feat: Enable project id usage by performing lookups where necessary. (#223)
* fix: Modify path construction methods to only have valid Path objects and allow project id or number usage. This enables called classes to determine more directly whether they need to call out to the project id to number mapping API. * feat: Enable project id usage in java client library. * fix: Revert samples changes until a new release happens. * fix: Add project id transform to assign and commit streams. * fix: Assorted fixes from PR. * fix: Fix new usage of old path modifiers. * fix: Add Serializable to path classes to allow use in beam tests.
1 parent b5ca1cc commit e30896e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+553
-431
lines changed

google-cloud-pubsublite/clirr-ignored-differences.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!-- see http://www.mojohaus.org/clirr-maven-plugin/examples/ignored-differences.html -->
33
<differences>
4+
<!-- Path construction has been modified: remove on next release. -->
5+
<difference>
6+
<differenceType>7002</differenceType>
7+
<className>com/google/cloud/pubsublite/*Path*</className>
8+
<method>*</method>
9+
</difference>
10+
<difference>
11+
<differenceType>7004</differenceType>
12+
<className>com/google/cloud/pubsublite/*Path*</className>
13+
<method>*</method>
14+
</difference>
15+
<difference>
16+
<differenceType>7005</differenceType>
17+
<className>com/google/cloud/pubsublite/*Path*</className>
18+
<method>*</method>
19+
<to>*</to>
20+
</difference>
21+
<difference>
22+
<differenceType>7013</differenceType>
23+
<className>com/google/cloud/pubsublite/*Path*</className>
24+
<method>*</method>
25+
</difference>
426
<!-- Blanket ignored files -->
527
<difference>
628
<differenceType>6000</differenceType>

google-cloud-pubsublite/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
<groupId>com.google.cloud</groupId>
4848
<artifactId>google-cloud-pubsub</artifactId>
4949
</dependency>
50+
<dependency>
51+
<groupId>com.google.cloud</groupId>
52+
<artifactId>google-cloud-resourcemanager</artifactId>
53+
<version>0.117.2-alpha</version>
54+
</dependency>
5055
<dependency>
5156
<groupId>com.google.api.grpc</groupId>
5257
<artifactId>proto-google-cloud-pubsub-v1</artifactId>

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/LocationPath.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,39 @@
1616

1717
package com.google.cloud.pubsublite;
1818

19-
import static com.google.common.base.Preconditions.checkArgument;
19+
import static com.google.cloud.pubsublite.internal.Preconditions.checkArgument;
2020

2121
import com.google.auto.value.AutoValue;
22+
import io.grpc.StatusException;
2223
import java.io.Serializable;
24+
import java.util.Arrays;
2325

24-
/**
25-
* A string wrapper representing a project and location. Should be structured like:
26-
*
27-
* <p>projects/&lt;project number&gt;/locations/&lt;cloud zone&gt;
28-
*/
26+
/** A string wrapper representing a project and location. */
2927
@AutoValue
3028
public abstract class LocationPath implements Serializable {
31-
/** The string value of this location path. */
32-
public abstract String value();
29+
public abstract ProjectPath project();
30+
31+
public abstract CloudZone location();
32+
33+
@Override
34+
public String toString() {
35+
return project() + "/locations/" + location();
36+
}
37+
38+
public static LocationPath of(ProjectPath project, CloudZone zone) {
39+
return new AutoValue_LocationPath(project, zone);
40+
}
3341

34-
/** Construct a LocationPath from its string value. */
35-
public static LocationPath of(String value) {
36-
checkArgument(!value.isEmpty());
37-
return new AutoValue_LocationPath(value);
42+
/**
43+
* Parse a location path. Should be structured like:
44+
*
45+
* <p>projects/&lt;project number&gt;/locations/&lt;cloud zone&gt;
46+
*/
47+
public static LocationPath parse(String path) throws StatusException {
48+
String[] splits = path.split("/");
49+
checkArgument(splits.length == 4);
50+
checkArgument(splits[2].equals("locations"));
51+
ProjectPath project = ProjectPath.parse(String.join("/", Arrays.copyOf(splits, 2)));
52+
return LocationPath.of(project, CloudZone.parse(splits[3]));
3853
}
3954
}

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/LocationPaths.java

Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,69 +16,29 @@
1616

1717
package com.google.cloud.pubsublite;
1818

19-
import static com.google.cloud.pubsublite.internal.ExtractStatus.toCanonical;
20-
import static com.google.cloud.pubsublite.internal.Preconditions.checkArgument;
21-
2219
import com.google.auto.value.AutoValue;
23-
import io.grpc.StatusException;
2420

2521
/** Helpers for constructing valid LocationPaths. */
2622
@AutoValue
2723
public abstract class LocationPaths {
28-
abstract ProjectNumber projectNumber();
24+
abstract ProjectIdOrNumber project();
2925

30-
abstract CloudZone zone();
26+
abstract CloudZone location();
3127

3228
/** Create a new LocationPath builder. */
3329
public static Builder newBuilder() {
3430
return new AutoValue_LocationPaths.Builder();
3531
}
3632

3733
@AutoValue.Builder
38-
public abstract static class Builder {
39-
/** The project number. */
40-
public abstract Builder setProjectNumber(ProjectNumber number);
41-
42-
/** The Google Cloud zone. */
43-
public abstract Builder setZone(CloudZone zone);
34+
public abstract static class Builder extends ProjectBuilderHelper<Builder> {
35+
public abstract Builder setLocation(CloudZone zone);
4436

4537
abstract LocationPaths autoBuild();
4638

47-
/** Build a new LocationPath. */
4839
public LocationPath build() {
4940
LocationPaths built = autoBuild();
50-
return LocationPath.of(
51-
String.format("projects/%s/locations/%s", built.projectNumber().value(), built.zone()));
41+
return LocationPath.of(ProjectPath.of(built.project()), built.location());
5242
}
5343
}
54-
55-
private static void checkSplits(String[] splits) throws StatusException {
56-
checkArgument(splits.length == 4);
57-
checkArgument(splits[0].equals("projects"));
58-
checkArgument(splits[2].equals("locations"));
59-
}
60-
61-
/** Check that the provided LocationPath is valid. */
62-
public static void check(LocationPath path) throws StatusException {
63-
ProjectNumber unusedProjectNumber = getProjectNumber(path);
64-
CloudZone unusedZone = getZone(path);
65-
}
66-
67-
/** Get the ProjectNumber from a LocationPath. */
68-
public static ProjectNumber getProjectNumber(LocationPath path) throws StatusException {
69-
String[] splits = path.value().split("/");
70-
checkSplits(splits);
71-
try {
72-
return ProjectNumber.of(Long.parseLong(splits[1]));
73-
} catch (NumberFormatException e) {
74-
throw toCanonical(e);
75-
}
76-
}
77-
78-
/** Get the CloudZone from a LocationPath. */
79-
public static CloudZone getZone(LocationPath path) throws StatusException {
80-
String[] splits = path.value().split("/");
81-
checkSplits(splits);
82-
return CloudZone.parse(splits[3]);
83-
}
8444
}

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/PartitionLookupUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static int numPartitions(TopicPath topic) throws StatusException {
3333
try (AdminClient client =
3434
AdminClient.create(
3535
AdminClientSettings.newBuilder()
36-
.setRegion(TopicPaths.getZone(topic).region())
36+
.setRegion(topic.location().location().region())
3737
.build())) {;
3838
return numPartitions(topic, client);
3939
} catch (Exception e) {
@@ -67,7 +67,7 @@ public static int numPartitions(SubscriptionPath subscription) throws StatusExce
6767
try (AdminClient client =
6868
AdminClient.create(
6969
AdminClientSettings.newBuilder()
70-
.setRegion(SubscriptionPaths.getZone(subscription).region())
70+
.setRegion(subscription.location().location().region())
7171
.build())) {
7272
return numPartitions(subscription, client);
7373
} catch (Exception e) {
@@ -83,7 +83,7 @@ public static int numPartitions(SubscriptionPath subscription, AdminClient clien
8383
throws StatusException {
8484
ApiFuture<Subscription> subscriptionFuture = client.getSubscription(subscription);
8585
try {
86-
return numPartitions(TopicPath.of(subscriptionFuture.get().getTopic()), client);
86+
return numPartitions(TopicPath.parse(subscriptionFuture.get().getTopic()), client);
8787
} catch (ExecutionException e) {
8888
throw ExtractStatus.toCanonical(e.getCause());
8989
} catch (Throwable t) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
abstract class ProjectBuilderHelper<Builder extends ProjectBuilderHelper<Builder>> {
20+
public abstract Builder setProject(ProjectIdOrNumber project);
21+
22+
public Builder setProject(ProjectId project) {
23+
setProject(ProjectIdOrNumber.of(project));
24+
return (Builder) this;
25+
}
26+
27+
public Builder setProject(ProjectNumber project) {
28+
setProject(ProjectIdOrNumber.of(project));
29+
return (Builder) this;
30+
}
31+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
import static com.google.cloud.pubsublite.internal.Preconditions.checkArgument;
20+
21+
import com.google.auto.value.AutoValue;
22+
import io.grpc.StatusException;
23+
import java.io.Serializable;
24+
25+
@AutoValue
26+
public abstract class ProjectId implements Serializable {
27+
public abstract String value();
28+
29+
@Override
30+
public String toString() {
31+
return value();
32+
}
33+
34+
public static ProjectId of(String value) throws StatusException {
35+
checkArgument(!value.isEmpty());
36+
return new AutoValue_ProjectId(value);
37+
}
38+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
import com.google.auto.value.AutoOneOf;
20+
import java.io.Serializable;
21+
22+
@AutoOneOf(ProjectIdOrNumber.Kind.class)
23+
public abstract class ProjectIdOrNumber implements Serializable {
24+
enum Kind {
25+
NAME,
26+
NUMBER
27+
}
28+
29+
public abstract Kind getKind();
30+
31+
public abstract ProjectId name();
32+
33+
public abstract ProjectNumber number();
34+
35+
public static ProjectIdOrNumber of(ProjectId name) {
36+
return AutoOneOf_ProjectIdOrNumber.name(name);
37+
}
38+
39+
public static ProjectIdOrNumber of(ProjectNumber number) {
40+
return AutoOneOf_ProjectIdOrNumber.number(number);
41+
}
42+
43+
@Override
44+
public String toString() {
45+
switch (getKind()) {
46+
case NAME:
47+
return name().toString();
48+
case NUMBER:
49+
return number().toString();
50+
default:
51+
throw new RuntimeException("Unknown case for ProjectIdOrNumber.");
52+
}
53+
}
54+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
import com.google.cloud.pubsublite.ProjectIdOrNumber.Kind;
20+
import com.google.cloud.pubsublite.internal.ExtractStatus;
21+
import com.google.cloud.resourcemanager.Project;
22+
import com.google.cloud.resourcemanager.ResourceManager;
23+
import com.google.cloud.resourcemanager.ResourceManagerOptions;
24+
import io.grpc.StatusException;
25+
26+
public class ProjectLookupUtils {
27+
private static final ResourceManager resourceManager =
28+
ResourceManagerOptions.getDefaultInstance().getService();
29+
30+
private static ProjectNumber getProjectNumber(ProjectId id) throws StatusException {
31+
try {
32+
Project project = resourceManager.get(id.toString());
33+
return ProjectNumber.of(project.getProjectNumber());
34+
} catch (Throwable t) {
35+
throw ExtractStatus.toCanonical(t);
36+
}
37+
}
38+
39+
public static ProjectPath toCannonical(ProjectPath project) throws StatusException {
40+
if (project.project().getKind() == Kind.NUMBER) return project;
41+
return ProjectPath.of(ProjectIdOrNumber.of(getProjectNumber(project.project().name())));
42+
}
43+
44+
public static LocationPath toCannonical(LocationPath location) throws StatusException {
45+
ProjectPath canonicalProject = toCannonical(location.project());
46+
return LocationPath.of(canonicalProject, location.location());
47+
}
48+
49+
public static SubscriptionPath toCannonical(SubscriptionPath subscription)
50+
throws StatusException {
51+
LocationPath canonicalLocation = toCannonical(subscription.location());
52+
return SubscriptionPath.of(canonicalLocation, subscription.name());
53+
}
54+
55+
public static TopicPath toCannonical(TopicPath topic) throws StatusException {
56+
LocationPath canonicalLocation = toCannonical(topic.location());
57+
return TopicPath.of(canonicalLocation, topic.name());
58+
}
59+
}

0 commit comments

Comments
 (0)