// 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 Cloud * Datastore Admin REST API. */ 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}. * *

Typical usage is: * *

   *     {@code Export export = datastoreAdmin.export(parameters ...);}
   *     {@code Operation operation = export.execute();}
   *     {@code while (!operation.isSuccessful()) { ...}}
   * 
* *

Please see the API * specification of the export method for details. * *

The following undocumented behaviors with regard to {@code outputUrlPrefix} have been * observed: * *

* * @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 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}. * *

Sample usage: find all operations started after 2018-10-31 00:00:00 UTC and has stopped: * *

   *     {@code String filter = "metadata.common.startTime>\"2018-10-31T0:0:0Z\" AND done=true";}
   *     {@code List operations = datastoreAdmin.list(filter);}
   * 
* *

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 { 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 { 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 { ListOperations(Optional 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 extends AbstractGoogleJsonClientRequest { /** * @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 responseClass) { super(client, requestMethod, uriTemplate, jsonContent, responseClass); } } /** * Model object that describes the JSON content in an export request. * *

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 kinds) { checkNotNull(outputUrlPrefix, "outputUrlPrefix"); this.outputUrlPrefix = outputUrlPrefix; this.entityFilter = new EntityFilter(kinds); } } }