Skip to content

Commit 6dac3fd

Browse files
authored
feat(bigtable): Add support for Logical Views in Admin API (#2519)
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/java-bigtable/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [x] Code coverage does not decrease (if any source code was changed) - [x] Appropriate docs were updated (if necessary) - [x] Rollback plan is reviewed and LGTMed - [x] All new data plane features have a completed end to end testing plan Fixes #<issue_number_goes_here> ☕️ If you write sample code, please follow the [samples format]( https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
1 parent 55cd719 commit 6dac3fd

12 files changed

+1102
-0
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java

+298
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,21 @@
2222
import com.google.api.gax.rpc.ApiExceptions;
2323
import com.google.api.gax.rpc.NotFoundException;
2424
import com.google.bigtable.admin.v2.DeleteAppProfileRequest;
25+
import com.google.bigtable.admin.v2.DeleteLogicalViewRequest;
2526
import com.google.bigtable.admin.v2.DeleteMaterializedViewRequest;
2627
import com.google.bigtable.admin.v2.GetAppProfileRequest;
28+
import com.google.bigtable.admin.v2.GetLogicalViewRequest;
2729
import com.google.bigtable.admin.v2.GetMaterializedViewRequest;
2830
import com.google.bigtable.admin.v2.ListAppProfilesRequest;
31+
import com.google.bigtable.admin.v2.ListLogicalViewsRequest;
2932
import com.google.bigtable.admin.v2.ListMaterializedViewsRequest;
3033
import com.google.bigtable.admin.v2.PartialUpdateClusterRequest;
3134
import com.google.cloud.Policy;
3235
import com.google.cloud.Policy.DefaultMarshaller;
3336
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage;
3437
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPagedResponse;
38+
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListLogicalViewsPage;
39+
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListLogicalViewsPagedResponse;
3540
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListMaterializedViewsPage;
3641
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListMaterializedViewsPagedResponse;
3742
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
@@ -41,13 +46,16 @@
4146
import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest;
4247
import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest;
4348
import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest;
49+
import com.google.cloud.bigtable.admin.v2.models.CreateLogicalViewRequest;
4450
import com.google.cloud.bigtable.admin.v2.models.CreateMaterializedViewRequest;
4551
import com.google.cloud.bigtable.admin.v2.models.Instance;
52+
import com.google.cloud.bigtable.admin.v2.models.LogicalView;
4653
import com.google.cloud.bigtable.admin.v2.models.MaterializedView;
4754
import com.google.cloud.bigtable.admin.v2.models.PartialListClustersException;
4855
import com.google.cloud.bigtable.admin.v2.models.PartialListInstancesException;
4956
import com.google.cloud.bigtable.admin.v2.models.UpdateAppProfileRequest;
5057
import com.google.cloud.bigtable.admin.v2.models.UpdateInstanceRequest;
58+
import com.google.cloud.bigtable.admin.v2.models.UpdateLogicalViewRequest;
5159
import com.google.cloud.bigtable.admin.v2.models.UpdateMaterializedViewRequest;
5260
import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub;
5361
import com.google.common.base.Verify;
@@ -1698,6 +1706,296 @@ public Void apply(Empty input) {
16981706
MoreExecutors.directExecutor());
16991707
}
17001708

1709+
/**
1710+
* Creates a new logical view.
1711+
*
1712+
* <p>Sample code:
1713+
*
1714+
* <pre>{@code
1715+
* LogicalView logicalView = client.createLogicalView(
1716+
* CreateLogicalViewRequest.of("my-instance", "my-new-logical-view")
1717+
* .setQuery(query)
1718+
* );
1719+
* }</pre>
1720+
*
1721+
* @see CreateLogicalViewRequest
1722+
*/
1723+
@SuppressWarnings("WeakerAccess")
1724+
public LogicalView createLogicalView(CreateLogicalViewRequest request) {
1725+
return ApiExceptions.callAndTranslateApiException(createLogicalViewAsync(request));
1726+
}
1727+
1728+
/**
1729+
* Asynchronously creates a new logical view.
1730+
*
1731+
* <p>Sample code:
1732+
*
1733+
* <pre>{@code
1734+
* ApiFuture<LogicalView> logicalViewFuture = client.createLogicalViewAsync(
1735+
* CreateLogicalViewRequest.of("my-instance", "my-new-logical-view")
1736+
* .setQuery(query)
1737+
* );
1738+
*
1739+
* LogicalView logicalView = logicalViewFuture.get();
1740+
* }</pre>
1741+
*
1742+
* @see CreateLogicalViewRequest
1743+
*/
1744+
@SuppressWarnings("WeakerAccess")
1745+
public ApiFuture<LogicalView> createLogicalViewAsync(CreateLogicalViewRequest request) {
1746+
return ApiFutures.transform(
1747+
stub.createLogicalViewOperationCallable().futureCall(request.toProto(projectId)),
1748+
new ApiFunction<com.google.bigtable.admin.v2.LogicalView, LogicalView>() {
1749+
@Override
1750+
public LogicalView apply(com.google.bigtable.admin.v2.LogicalView proto) {
1751+
return LogicalView.fromProto(proto);
1752+
}
1753+
},
1754+
MoreExecutors.directExecutor());
1755+
}
1756+
1757+
/**
1758+
* Gets the logical view by ID.
1759+
*
1760+
* <p>Sample code:
1761+
*
1762+
* <pre>{@code
1763+
* LogicalView logicalView = client.getLogicalView("my-instance", "my-logical-view");
1764+
* }</pre>
1765+
*
1766+
* @see LogicalView
1767+
*/
1768+
public LogicalView getLogicalView(String instanceId, String logicalViewId) {
1769+
return ApiExceptions.callAndTranslateApiException(
1770+
getLogicalViewAsync(instanceId, logicalViewId));
1771+
}
1772+
1773+
/**
1774+
* Asynchronously gets the logical view by ID.
1775+
*
1776+
* <p>Sample code:
1777+
*
1778+
* <pre>{@code
1779+
* ApiFuture<LogicalView> logicalViewFuture = client.getLogicalViewAsync("my-instance", "my-logical-view");
1780+
*
1781+
* LogicalView logicalView = logicalViewFuture.get();
1782+
* }</pre>
1783+
*
1784+
* @see LogicalView
1785+
*/
1786+
@SuppressWarnings("WeakerAccess")
1787+
public ApiFuture<LogicalView> getLogicalViewAsync(String instanceId, String logicalViewId) {
1788+
String name = NameUtil.formatLogicalViewName(projectId, instanceId, logicalViewId);
1789+
1790+
GetLogicalViewRequest request = GetLogicalViewRequest.newBuilder().setName(name).build();
1791+
1792+
return ApiFutures.transform(
1793+
stub.getLogicalViewCallable().futureCall(request),
1794+
new ApiFunction<com.google.bigtable.admin.v2.LogicalView, LogicalView>() {
1795+
@Override
1796+
public LogicalView apply(com.google.bigtable.admin.v2.LogicalView proto) {
1797+
return LogicalView.fromProto(proto);
1798+
}
1799+
},
1800+
MoreExecutors.directExecutor());
1801+
}
1802+
1803+
/**
1804+
* Lists all logical views of the specified instance.
1805+
*
1806+
* <p>Sample code:
1807+
*
1808+
* <pre>{@code
1809+
* List<LogicalView> logicalViews = client.listLogicalViews("my-instance");
1810+
* }</pre>
1811+
*
1812+
* @see LogicalView
1813+
*/
1814+
@SuppressWarnings("WeakerAccess")
1815+
public List<LogicalView> listLogicalViews(String instanceId) {
1816+
return ApiExceptions.callAndTranslateApiException(listLogicalViewsAsync(instanceId));
1817+
}
1818+
1819+
/**
1820+
* Asynchronously lists all logical views of the specified instance.
1821+
*
1822+
* <p>Sample code:
1823+
*
1824+
* <pre>{@code
1825+
* ApiFuture<List<LogicalView>> logicalViewsFuture = client.listLogicalViewsAsync("my-instance");
1826+
*
1827+
* List<LogicalView> logicalViews = logicalViewFuture.get();
1828+
* }</pre>
1829+
*
1830+
* @see LogicalView
1831+
*/
1832+
@SuppressWarnings("WeakerAccess")
1833+
public ApiFuture<List<LogicalView>> listLogicalViewsAsync(String instanceId) {
1834+
String instanceName = NameUtil.formatInstanceName(projectId, instanceId);
1835+
1836+
ListLogicalViewsRequest request =
1837+
ListLogicalViewsRequest.newBuilder().setParent(instanceName).build();
1838+
1839+
// TODO(igorbernstein2): try to upstream pagination spooling or figure out a way to expose the
1840+
// paginated responses while maintaining the wrapper facade.
1841+
1842+
// Fetches the first page.
1843+
ApiFuture<ListLogicalViewsPage> firstPageFuture =
1844+
ApiFutures.transform(
1845+
stub.listLogicalViewsPagedCallable().futureCall(request),
1846+
new ApiFunction<ListLogicalViewsPagedResponse, ListLogicalViewsPage>() {
1847+
@Override
1848+
public ListLogicalViewsPage apply(ListLogicalViewsPagedResponse response) {
1849+
return response.getPage();
1850+
}
1851+
},
1852+
MoreExecutors.directExecutor());
1853+
1854+
// Fetches the rest of the pages by chaining the futures.
1855+
ApiFuture<List<com.google.bigtable.admin.v2.LogicalView>> allProtos =
1856+
ApiFutures.transformAsync(
1857+
firstPageFuture,
1858+
new ApiAsyncFunction<
1859+
ListLogicalViewsPage, List<com.google.bigtable.admin.v2.LogicalView>>() {
1860+
List<com.google.bigtable.admin.v2.LogicalView> responseAccumulator =
1861+
Lists.newArrayList();
1862+
1863+
@Override
1864+
public ApiFuture<List<com.google.bigtable.admin.v2.LogicalView>> apply(
1865+
ListLogicalViewsPage page) {
1866+
// Add all entries from the page
1867+
responseAccumulator.addAll(Lists.newArrayList(page.getValues()));
1868+
1869+
// If this is the last page, just return the accumulated responses.
1870+
if (!page.hasNextPage()) {
1871+
return ApiFutures.immediateFuture(responseAccumulator);
1872+
}
1873+
1874+
// Otherwise fetch the next page.
1875+
return ApiFutures.transformAsync(
1876+
page.getNextPageAsync(), this, MoreExecutors.directExecutor());
1877+
}
1878+
},
1879+
MoreExecutors.directExecutor());
1880+
1881+
// Wraps all of the accumulated protos.
1882+
return ApiFutures.transform(
1883+
allProtos,
1884+
new ApiFunction<List<com.google.bigtable.admin.v2.LogicalView>, List<LogicalView>>() {
1885+
@Override
1886+
public List<LogicalView> apply(List<com.google.bigtable.admin.v2.LogicalView> input) {
1887+
List<LogicalView> results = Lists.newArrayListWithCapacity(input.size());
1888+
for (com.google.bigtable.admin.v2.LogicalView logicalView : input) {
1889+
results.add(LogicalView.fromProto(logicalView));
1890+
}
1891+
return results;
1892+
}
1893+
},
1894+
MoreExecutors.directExecutor());
1895+
}
1896+
1897+
/**
1898+
* Updates an existing logical view.
1899+
*
1900+
* <p>Sample code:
1901+
*
1902+
* <pre>{@code
1903+
* LogicalView existingLogicalView = client.getLogicalView("my-instance", "my-logical-view");
1904+
*
1905+
* LogicalView updatedLogicalView = client.updateLogicalView(
1906+
* UpdateLogicalViewRequest.of(existingLogicalView)
1907+
* .setQuery(query)
1908+
* );
1909+
* }</pre>
1910+
*
1911+
* @see UpdateLogicalViewRequest
1912+
*/
1913+
@SuppressWarnings("WeakerAccess")
1914+
public LogicalView updateLogicalView(UpdateLogicalViewRequest request) {
1915+
return ApiExceptions.callAndTranslateApiException(updateLogicalViewAsync(request));
1916+
}
1917+
1918+
/**
1919+
* Asynchronously updates an existing logical view.
1920+
*
1921+
* <p>Sample code:
1922+
*
1923+
* <pre>{@code
1924+
* ApiFuture<LogicalView> existingLogicalViewFuture = client.getLogicalViewAsync("my-instance", "my-logical-view");
1925+
*
1926+
* ApiFuture<LogicalView> updatedLogicalViewFuture = ApiFutures.transformAsync(
1927+
* existingLogicalViewFuture,
1928+
* new ApiAsyncFunction<LogicalView, LogicalView>() {
1929+
* public ApiFuture<LogicalView> apply(LogicalView existingLogicalView) {
1930+
* return client.updateLogicalViewAsync(
1931+
* UpdateLogicalViewRequest.of(existingLogicalView)
1932+
* .setQuery(query)
1933+
* );
1934+
* }
1935+
* },
1936+
* MoreExecutors.directExecutor()
1937+
* );
1938+
*
1939+
* ApiFuture<LogicalView> logicalView = updatedLogicalViewFuture.get();
1940+
* }</pre>
1941+
*
1942+
* @see UpdateLogicalViewRequest
1943+
*/
1944+
@SuppressWarnings("WeakerAccess")
1945+
public ApiFuture<LogicalView> updateLogicalViewAsync(UpdateLogicalViewRequest request) {
1946+
return ApiFutures.transform(
1947+
stub.updateLogicalViewOperationCallable().futureCall(request.toProto(projectId)),
1948+
new ApiFunction<com.google.bigtable.admin.v2.LogicalView, LogicalView>() {
1949+
@Override
1950+
public LogicalView apply(com.google.bigtable.admin.v2.LogicalView proto) {
1951+
return LogicalView.fromProto(proto);
1952+
}
1953+
},
1954+
MoreExecutors.directExecutor());
1955+
}
1956+
1957+
/**
1958+
* Deletes the specified logical view.
1959+
*
1960+
* <p>Sample code:
1961+
*
1962+
* <pre>{@code
1963+
* client.deleteLogicalView("my-instance", "my-logical-view");
1964+
* }</pre>
1965+
*/
1966+
@SuppressWarnings("WeakerAccess")
1967+
public void deleteLogicalView(String instanceId, String logicalViewId) {
1968+
ApiExceptions.callAndTranslateApiException(deleteLogicalViewAsync(instanceId, logicalViewId));
1969+
}
1970+
1971+
/**
1972+
* Asynchronously deletes the specified logical view.
1973+
*
1974+
* <p>Sample code:
1975+
*
1976+
* <pre>{@code
1977+
* ApiFuture<Void> deleteFuture = client.deleteLogicalViewAsync("my-instance", "my-logical-view");
1978+
*
1979+
* deleteFuture.get();
1980+
* }</pre>
1981+
*/
1982+
@SuppressWarnings("WeakerAccess")
1983+
public ApiFuture<Void> deleteLogicalViewAsync(String instanceId, String logicalViewId) {
1984+
1985+
String name = NameUtil.formatLogicalViewName(projectId, instanceId, logicalViewId);
1986+
DeleteLogicalViewRequest request = DeleteLogicalViewRequest.newBuilder().setName(name).build();
1987+
1988+
return ApiFutures.transform(
1989+
stub.deleteLogicalViewCallable().futureCall(request),
1990+
new ApiFunction<Empty, Void>() {
1991+
@Override
1992+
public Void apply(Empty input) {
1993+
return null;
1994+
}
1995+
},
1996+
MoreExecutors.directExecutor());
1997+
}
1998+
17011999
/**
17022000
* Simple adapter to expose {@link DefaultMarshaller} to this class. It enables this client to
17032001
* convert to/from IAM wrappers and protobufs.

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminSettings.java

+5
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public String toString() {
118118
.add("listMaterializedViewsSettings", stubSettings.listMaterializedViewsSettings())
119119
.add("updateMaterializedViewSettings", stubSettings.updateMaterializedViewSettings())
120120
.add("deleteMaterializedViewSettings", stubSettings.deleteMaterializedViewSettings())
121+
.add("createLogicalViewSettings", stubSettings.createLogicalViewSettings())
122+
.add("getLogicalViewSettings", stubSettings.getLogicalViewSettings())
123+
.add("listLogicalViewsSettings", stubSettings.listLogicalViewsSettings())
124+
.add("updateLogicalViewSettings", stubSettings.updateLogicalViewSettings())
125+
.add("deleteLogicalViewSettings", stubSettings.deleteLogicalViewSettings())
121126
.add("stubSettings", stubSettings)
122127
.toString();
123128
}

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/internal/NameUtil.java

+5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ public static String formatMaterializedViewName(
5555
return formatInstanceName(projectId, instanceId) + "/materializedViews/" + materializedViewId;
5656
}
5757

58+
public static String formatLogicalViewName(
59+
@Nonnull String projectId, @Nonnull String instanceId, @Nonnull String logicalViewId) {
60+
return formatInstanceName(projectId, instanceId) + "/logicalViews/" + logicalViewId;
61+
}
62+
5863
public static String formatLocationName(String projectId, String zone) {
5964
return formatProjectName(projectId) + "/locations/" + zone;
6065
}

0 commit comments

Comments
 (0)