Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .kokoro/continuous/bigtable-it.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ env_vars: {

env_vars: {
key: "INTEGRATION_TEST_ARGS"
value: "google-cloud-clients/google-cloud-bigtable -Dbigtable.env=prod -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
value: "google-cloud-clients/google-cloud-bigtable -pl google-cloud-testing/google-cloud-bigtable-emulator -P bigtable-emulator-it,bigtable-prod-it -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
}

env_vars: {
Expand Down
2 changes: 1 addition & 1 deletion .kokoro/nightly/bigtable-it.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ env_vars: {

env_vars: {
key: "INTEGRATION_TEST_ARGS"
value: "google-cloud-clients/google-cloud-bigtable -Dbigtable.env=prod -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
value: "google-cloud-clients/google-cloud-bigtable -pl google-cloud-testing/google-cloud-bigtable-emulator -P bigtable-emulator-it,bigtable-prod-it -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
}

env_vars: {
Expand Down
2 changes: 1 addition & 1 deletion .kokoro/presubmit/bigtable-it.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ env_vars: {

env_vars: {
key: "INTEGRATION_TEST_ARGS"
value: "google-cloud-clients/google-cloud-bigtable -Dbigtable.env=prod -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
value: "google-cloud-clients/google-cloud-bigtable -pl google-cloud-testing/google-cloud-bigtable-emulator -P bigtable-emulator-it,bigtable-prod-it -Dbigtable.project=gcloud-devel -Dbigtable.instance=google-cloud-bigtable -Dbigtable.table=integration-tests"
}

env_vars: {
Expand Down
10 changes: 5 additions & 5 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ Here is an example that clears the dataset created in Step 3.
### Testing code that uses Bigtable

Bigtable integration tests can either be run against an emulator or a real Bigtable table. The
target environment can be selected via the `bigtable.env` system property. By default it is set to
`emulator` and the other option is `prod`.
target environment can be selected by setting a maven profile. By default it is set to
`bigtable-emulator-it` and other options are `bigtable-prod-it` and `bigtable-directpath-it`.

To use the `prod` environment:
To use the `bigtable-prod-it` and `bigtable-directpath-it` environments:
1. Set up the target table using `google-cloud-bigtable/scripts/setup-test-table.sh`
2. Download the [JSON service account credentials file][create-service-account] from the Google
Developer's Console.
3. Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS` to the path of the credentials file
4. Set the system property `bigtable.env=prod`, `bigtable.project`, `bigtable.instance` and
4. Enable the profile and the system properties `bigtable.project`, `bigtable.instance` and
`bigtable.table` to created earlier. Example:
```shell
mvn verify -am -pl google-cloud-bigtable \
-Dbigtable.env=prod \
-P bigtable-prod-it \
-Dbigtable.project=my-project
-Dbigtable.instance=my-instance
-Dbigtable.table=my-table
Expand Down
104 changes: 96 additions & 8 deletions google-cloud-clients/google-cloud-bigtable/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,108 @@
<scope>test</scope>
</dependency>
</dependencies>

<profiles>
<profile>
<id>bigtable-emulator-it</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>

<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>emulator-it</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<bigtable.env>emulator</bigtable.env>
</systemPropertyVariables>
<test>com.google.cloud.bigtable.data.v2.it.**</test>
<summaryFile>target/failsafe-reports/failsafe-summary-emulator-it.xml</summaryFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

<profile>
<id>bigtable-prod-it</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>prod-it</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<bigtable.env>prod</bigtable.env>
</systemPropertyVariables>
<test>com.google.cloud.bigtable.data.v2.it.**</test>
<test>com.google.cloud.bigtable.admin.v2.it.**</test>
<summaryFile>target/failsafe-reports/failsafe-summary-prod-it.xml</summaryFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

<profile>
<id>bigtable-directpath-it</id>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>directpath-it</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<bigtable.env>direct_path</bigtable.env>
<!-- TODO(igorbernstein): This property should be auto set by gax -->
<io.grpc.internal.DnsNameResolverProvider.enable_grpclb>true</io.grpc.internal.DnsNameResolverProvider.enable_grpclb>
</systemPropertyVariables>
<!-- Enable directpath for bigtable -->
<environmentVariables>
<GOOGLE_CLOUD_ENABLE_DIRECT_PATH>bigtable</GOOGLE_CLOUD_ENABLE_DIRECT_PATH>
</environmentVariables>
<!-- TODO(igorbernstein): Once the control plane is accessible via directpath, add admin tests -->
<test>com.google.cloud.bigtable.data.v2.it.**</test>
<summaryFile>target/failsafe-reports/failsafe-summary-directpath-it.xml</summaryFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<parallel>classes</parallel>
<perCoreThreadCount>true</perCoreThreadCount>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@

# Set up a table to use for integration tests.

set -x
set -e
set -u

ADMIN_HOSTS=(
"bigtableadmin.googleapis.com:443"
"test-bigtableadmin.sandbox.googleapis.com:443"
)

ZONE=us-central1-b
FAMILY=cf

# Format: projects/<project-id>/instances/<instance-id>/tables/<table-id>
TABLE_NAME=$1
Expand All @@ -16,6 +25,24 @@ else
exit 1
fi

cbt -project $PROJECT_ID -instance $INSTANCE_ID createtable $TABLE_ID
cbt -project $PROJECT_ID -instance $INSTANCE_ID createfamily $TABLE_ID cf
cbt -project $PROJECT_ID -instance $INSTANCE_ID setgcpolicy $TABLE_ID cf maxversions=1
call_cbt() {
cbt -admin-endpoint="${ADMIN_HOST}" -project "${PROJECT_ID}" -instance "${INSTANCE_ID}" "$@"
}

for ADMIN_HOST in "${ADMIN_HOSTS[@]}"; do
# Ensure that the instance exists.
if ! call_cbt listinstances | grep -q "${INSTANCE_ID}"; then
call_cbt createinstance "${INSTANCE_ID}" "${INSTANCE_ID}" "${INSTANCE_ID}-c0" "${ZONE}" 1 SSD
fi

# Ensure that the table exists
if ! call_cbt -instance ${INSTANCE_ID} ls | grep -q "^${TABLE_ID}\$"; then
call_cbt createtable ${TABLE_ID}
fi

# Ensure that the family exists
if ! call_cbt ls "${TABLE_ID}" | grep -q "^$FAMILY\b"; then
call_cbt createfamily "${TABLE_ID}" "${FAMILY}"
call_cbt setgcpolicy "${TABLE_ID}" "${FAMILY}" maxversions=1
fi
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.bigtable.data.v2.it.env;

import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.api.gax.rpc.ServerStream;
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
import com.google.cloud.bigtable.data.v2.models.Query;
import com.google.cloud.bigtable.data.v2.models.Row;
import com.google.cloud.bigtable.data.v2.models.RowMutation;
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
* Test environment that uses an existing bigtable table in the directpath environment.
*
* <p>The test environment can be accessed via both, CFE and direct path. The transport is
* controlled via the environment variable {@code GOOGLE_CLOUD_ENABLE_DIRECT_PATH}. Which contains
* comma delimited list of service names that should be accessed via direct path.
*
* <p>The target table must have a pre-existing family {@code cf}. The target table is configured
* via the system properties:
*
* <ul>
* <li>{@code bigtable.project}
* <li>{@code bigtable.instance}
* <li>{@code bigtable.table}
* </ul>
*/
public class DirectPathEnv implements TestEnv {
// TODO(igorbernstein): move direct path conditional logic to gax
private static final String DIRECT_PATH_ENV_VAR = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH";
private static final String DIRECT_PATH_END_POINT =
"testdirectpath-bigtable.sandbox.googleapis.com:443";

private static final String PROJECT_PROPERTY_NAME = "bigtable.project";
private static final String INSTANCE_PROPERTY_NAME = "bigtable.instance";
private static final String TABLE_PROPERTY_NAME = "bigtable.table";

private final boolean directPathEnabled;
private final String projectId;
private final String instanceId;
private final String tableId;
private static final String FAMILY_ID = "cf";
private String rowPrefix;

private BigtableDataClient dataClient;

static DirectPathEnv create() {
return new DirectPathEnv(
isDirectPathEnabled(),
getRequiredProperty(PROJECT_PROPERTY_NAME),
getRequiredProperty(INSTANCE_PROPERTY_NAME),
getRequiredProperty(TABLE_PROPERTY_NAME));
}

public DirectPathEnv(
boolean directPathEnabled, String projectId, String instanceId, String tableId) {
this.directPathEnabled = directPathEnabled;
this.projectId = projectId;
this.instanceId = instanceId;
this.tableId = tableId;
this.rowPrefix = UUID.randomUUID() + "-";
}

@Override
public void start() throws IOException {
BigtableDataSettings.Builder settingsBuilder =
BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId);

// Direct path test environment uses a different endpoint.
settingsBuilder.stubSettings().setEndpoint(DIRECT_PATH_END_POINT);

// TODO(igorbernstein): move direct path conditional logic to gax
// Direct path environment can be accessed via CFE or direct path. When using direct path,
// disable connection pooling.
if (directPathEnabled) {
settingsBuilder
.stubSettings()
.setTransportChannelProvider(
EnhancedBigtableStubSettings.defaultGrpcTransportProviderBuilder()
.setPoolSize(1)
.build());
}

dataClient = BigtableDataClient.create(settingsBuilder.build());
}

@Override
public void stop() throws Exception {
deleteRows();
dataClient.close();
}

@Override
public BigtableDataClient getDataClient() {
return dataClient;
}

@Override
public String getProjectId() {
return projectId;
}

@Override
public String getInstanceId() {
return instanceId;
}

@Override
public String getTableId() {
return tableId;
}

@Override
public String getFamilyId() {
return FAMILY_ID;
}

@Override
public String getRowPrefix() {
return rowPrefix;
}

private void deleteRows() throws InterruptedException, ExecutionException, TimeoutException {
Query query = Query.create(tableId).prefix(rowPrefix);

List<ApiFuture<Void>> futures = Lists.newArrayList();
ServerStream<Row> rows = dataClient.readRows(query);
for (Row row : rows) {
ApiFuture<Void> future =
dataClient.mutateRowAsync(RowMutation.create(tableId, row.getKey()).deleteRow());
futures.add(future);
}

ApiFutures.allAsList(futures).get(10, TimeUnit.MINUTES);
}

private static String getRequiredProperty(String prop) {
String value = System.getProperty(prop);
if (value == null || value.isEmpty()) {
throw new RuntimeException("Missing system property: " + prop);
}
return value;
}

// TODO(igorbernstein): move direct path conditional logic to gax
private static boolean isDirectPathEnabled() {
String whiteList = System.getenv(DIRECT_PATH_ENV_VAR);
if (whiteList == null) {
return false;
}

for (String service : whiteList.split(",")) {
if (!service.isEmpty() && DIRECT_PATH_END_POINT.contains(service)) {
return true;
}
}
return false;
}
}
Loading