mirror of
https://github.com/google/nomulus.git
synced 2025-05-02 21:17:50 +02:00
Add {java,tests}/google/registry/export/datastore to open source. This is part of the migration to Datastore Managed Import/Export for backup. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=221800709
223 lines
8.1 KiB
Java
223 lines
8.1 KiB
Java
// Copyright 2018 The Nomulus Authors. All Rights Reserved.
|
|
//
|
|
// 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
|
|
//
|
|
// http://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 google.registry.export.datastore;
|
|
|
|
import static com.google.common.base.Preconditions.checkArgument;
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
import com.google.api.client.googleapis.services.json.AbstractGoogleJsonClient;
|
|
import com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest;
|
|
import com.google.api.client.http.HttpRequestInitializer;
|
|
import com.google.api.client.http.HttpTransport;
|
|
import com.google.api.client.json.GenericJson;
|
|
import com.google.api.client.json.JsonFactory;
|
|
import com.google.api.client.util.Key;
|
|
import com.google.common.base.Strings;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
|
|
/**
|
|
* Java client to <a href="https://cloud.google.com/datastore/docs/reference/admin/rest/">Cloud
|
|
* Datastore Admin REST API</a>.
|
|
*/
|
|
public class DatastoreAdmin extends AbstractGoogleJsonClient {
|
|
|
|
private static final String ROOT_URL = "https://datastore.googleapis.com/v1/";
|
|
private static final String SERVICE_PATH = "";
|
|
|
|
// GCP project that this instance is associated with.
|
|
private final String projectId;
|
|
|
|
protected DatastoreAdmin(Builder builder) {
|
|
super(builder);
|
|
this.projectId = checkNotNull(builder.projectId, "GCP projectId missing.");
|
|
}
|
|
|
|
/**
|
|
* Returns an {@link Export} request that starts exporting all Cloud Datastore databases owned by
|
|
* the GCP project identified by {@link #projectId}.
|
|
*
|
|
* <p>Typical usage is:
|
|
*
|
|
* <pre>
|
|
* {@code Export export = datastoreAdmin.export(parameters ...);}
|
|
* {@code Operation operation = export.execute();}
|
|
* {@code while (!operation.isSuccessful()) { ...}}
|
|
* </pre>
|
|
*
|
|
* <p>Please see the <a
|
|
* href="https://cloud.google.com/datastore/docs/reference/admin/rest/v1/projects/export">API
|
|
* specification of the export method for details</a>.
|
|
*
|
|
* <p>The following undocumented behaviors with regard to {@code outputUrlPrefix} have been
|
|
* observed:
|
|
*
|
|
* <ul>
|
|
* <li>If outputUrlPrefix refers to a GCS bucket, exported data will be nested deeper in the
|
|
* bucket with a timestamped path. This is useful when periodical backups are desired
|
|
* <li>If outputUrlPrefix is a already a nested path in a GCS bucket, exported data will be put
|
|
* under this path. This means that a nested path is not reusable, since the export process
|
|
* by default would not overwrite existing files.
|
|
* </ul>
|
|
*
|
|
* @param outputUrlPrefix the full resource URL of the external storage location
|
|
* @param kinds the datastore 'kinds' to be exported
|
|
*/
|
|
public Export export(String outputUrlPrefix, List<String> kinds) {
|
|
return new Export(new ExportRequest(outputUrlPrefix, kinds));
|
|
}
|
|
|
|
/**
|
|
* Returns a {@link Get} request that retrieves the details of an export or import {@link
|
|
* Operation}.
|
|
*
|
|
* @param operationName name of the {@code Operation} as returned by an export or import request
|
|
*/
|
|
public Get get(String operationName) {
|
|
return new Get(operationName);
|
|
}
|
|
|
|
/**
|
|
* Returns a {@link ListOperations} request that retrieves all export or import {@link Operation
|
|
* operations} matching {@code filter}.
|
|
*
|
|
* <p>Sample usage: find all operations started after 2018-10-31 00:00:00 UTC and has stopped:
|
|
*
|
|
* <pre>
|
|
* {@code String filter = "metadata.common.startTime>\"2018-10-31T0:0:0Z\" AND done=true";}
|
|
* {@code List<Operation> operations = datastoreAdmin.list(filter);}
|
|
* </pre>
|
|
*
|
|
* <p>Please refer to {@link Operation} for how to reference operation properties.
|
|
*/
|
|
public ListOperations list(String filter) {
|
|
checkArgument(!Strings.isNullOrEmpty(filter), "Filter must not be null or empty.");
|
|
return new ListOperations(Optional.of(filter));
|
|
}
|
|
|
|
/**
|
|
* Returns a {@link ListOperations} request that retrieves all export or import {@link Operation *
|
|
* operations}.
|
|
*/
|
|
public ListOperations listAll() {
|
|
return new ListOperations(Optional.empty());
|
|
}
|
|
|
|
/** Builder for {@link DatastoreAdmin}. */
|
|
public static class Builder extends AbstractGoogleJsonClient.Builder {
|
|
|
|
private String projectId;
|
|
|
|
public Builder(
|
|
HttpTransport httpTransport,
|
|
JsonFactory jsonFactory,
|
|
HttpRequestInitializer httpRequestInitializer) {
|
|
super(httpTransport, jsonFactory, ROOT_URL, SERVICE_PATH, httpRequestInitializer, false);
|
|
}
|
|
|
|
@Override
|
|
public Builder setApplicationName(String applicationName) {
|
|
return (Builder) super.setApplicationName(applicationName);
|
|
}
|
|
|
|
/** Sets the GCP project ID of the Cloud Datastore databases being managed. */
|
|
public Builder setProjectId(String projectId) {
|
|
this.projectId = projectId;
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public DatastoreAdmin build() {
|
|
return new DatastoreAdmin(this);
|
|
}
|
|
}
|
|
|
|
/** A request to export Cloud Datastore databases. */
|
|
public class Export extends DatastoreAdminRequest<Operation> {
|
|
|
|
Export(ExportRequest exportRequest) {
|
|
super(
|
|
DatastoreAdmin.this,
|
|
"POST",
|
|
"projects/{projectId}:export",
|
|
exportRequest,
|
|
Operation.class);
|
|
set("projectId", projectId);
|
|
}
|
|
}
|
|
|
|
/** A request to retrieve details of an export or import operation. */
|
|
public class Get extends DatastoreAdminRequest<Operation> {
|
|
|
|
Get(String operationName) {
|
|
super(DatastoreAdmin.this, "GET", operationName, null, Operation.class);
|
|
}
|
|
}
|
|
|
|
/** A request to retrieve all export or import operations matching a given filter. */
|
|
public class ListOperations extends DatastoreAdminRequest<Operation.OperationList> {
|
|
|
|
ListOperations(Optional<String> filter) {
|
|
super(
|
|
DatastoreAdmin.this,
|
|
"GET",
|
|
"projects/{projectId}/operations",
|
|
null,
|
|
Operation.OperationList.class);
|
|
set("projectId", projectId);
|
|
filter.ifPresent(f -> set("filter", f));
|
|
}
|
|
}
|
|
|
|
/** Base class of all DatastoreAdmin requests. */
|
|
abstract static class DatastoreAdminRequest<T> extends AbstractGoogleJsonClientRequest<T> {
|
|
/**
|
|
* @param client Google JSON client
|
|
* @param requestMethod HTTP Method
|
|
* @param uriTemplate URI template for the path relative to the base URL. If it starts with a
|
|
* "/" the base path from the base URL will be stripped out. The URI template can also be a
|
|
* full URL. URI template expansion is done using {@link
|
|
* com.google.api.client.http.UriTemplate#expand(String, String, Object, boolean)}
|
|
* @param jsonContent POJO that can be serialized into JSON content or {@code null} for none
|
|
* @param responseClass response class to parse into
|
|
*/
|
|
protected DatastoreAdminRequest(
|
|
DatastoreAdmin client,
|
|
String requestMethod,
|
|
String uriTemplate,
|
|
Object jsonContent,
|
|
Class<T> responseClass) {
|
|
super(client, requestMethod, uriTemplate, jsonContent, responseClass);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Model object that describes the JSON content in an export request.
|
|
*
|
|
* <p>Please note that some properties defined in the API are excluded, e.g., {@code databaseId}
|
|
* (not supported by Cloud Datastore) and labels (not used by Domain Registry).
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
static class ExportRequest extends GenericJson {
|
|
@Key private final String outputUrlPrefix;
|
|
@Key private final EntityFilter entityFilter;
|
|
|
|
ExportRequest(String outputUrlPrefix, List<String> kinds) {
|
|
checkNotNull(outputUrlPrefix, "outputUrlPrefix");
|
|
this.outputUrlPrefix = outputUrlPrefix;
|
|
this.entityFilter = new EntityFilter(kinds);
|
|
}
|
|
}
|
|
}
|