mirror of
https://github.com/google/nomulus.git
synced 2025-07-25 03:58:34 +02:00
Remove backported LocalStorageHelper (#1267)
* Remove backported LocalStorageHelper The released version on Maven Central now contains the fix to the serialization bug.
This commit is contained in:
parent
320d4db5fb
commit
99382f7656
24 changed files with 69 additions and 701 deletions
|
@ -25,10 +25,10 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
|||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ofy.CommitLogBucket;
|
||||
import google.registry.model.ofy.CommitLogCheckpoint;
|
||||
|
|
|
@ -29,13 +29,13 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.flogger.LoggerConfig;
|
||||
import com.google.common.testing.TestLogHandler;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
|
@ -36,6 +36,7 @@ import static org.mockito.Mockito.spy;
|
|||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -44,7 +45,6 @@ import com.google.common.truth.Truth8;
|
|||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule;
|
||||
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
|
|
|
@ -28,6 +28,7 @@ import static org.joda.time.DateTimeZone.UTC;
|
|||
import com.google.appengine.api.datastore.DatastoreServiceFactory;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -36,7 +37,6 @@ import com.google.common.primitives.Longs;
|
|||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.ofy.CommitLogBucket;
|
||||
|
|
|
@ -41,6 +41,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||
import static org.joda.time.Duration.standardDays;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -50,7 +51,6 @@ import com.google.common.collect.Streams;
|
|||
import com.google.common.io.BaseEncoding;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.keyring.api.PgpHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
|
|
|
@ -29,11 +29,11 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.StorageException;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.export.ExportDomainListsAction.ExportDomainListsReducer;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
|
|
|
@ -19,11 +19,11 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.BlobInfo;
|
||||
import com.google.cloud.storage.StorageOptions;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -1,517 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* 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.gcs.backport;
|
||||
|
||||
import com.google.api.client.util.DateTime;
|
||||
import com.google.api.services.storage.model.Bucket;
|
||||
import com.google.api.services.storage.model.ServiceAccount;
|
||||
import com.google.api.services.storage.model.StorageObject;
|
||||
import com.google.cloud.Tuple;
|
||||
import com.google.cloud.storage.Storage;
|
||||
import com.google.cloud.storage.StorageException;
|
||||
import com.google.cloud.storage.spi.v1.StorageRpc;
|
||||
import com.google.cloud.storage.testing.StorageRpcTestBase;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
/**
|
||||
* A bare-bones in-memory implementation of StorageRpc, meant for testing.
|
||||
*
|
||||
* <p>This class is <i>not</i> thread-safe. It's also (currently) limited in the following ways:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Supported
|
||||
* <ul>
|
||||
* <li>object create
|
||||
* <li>object get
|
||||
* <li>object delete
|
||||
* <li>list the contents of a bucket
|
||||
* <li>generations
|
||||
* </ul>
|
||||
* <li>Unsupported
|
||||
* <ul>
|
||||
* <li>bucket create
|
||||
* <li>bucket get
|
||||
* <li>bucket delete
|
||||
* <li>list all buckets
|
||||
* <li>file attributes
|
||||
* <li>patch
|
||||
* <li>continueRewrite
|
||||
* <li>createBatch
|
||||
* <li>checksums, etags
|
||||
* <li>IAM operations
|
||||
* <li>BucketLock operations
|
||||
* <li>HMAC key operations
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
@NotThreadSafe
|
||||
class FakeStorageRpc extends StorageRpcTestBase {
|
||||
|
||||
private static final SimpleDateFormat RFC_3339_FORMATTER =
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
|
||||
// fullname -> metadata
|
||||
Map<String, StorageObject> metadata = new HashMap<>();
|
||||
// fullname -> contents
|
||||
Map<String, byte[]> contents = new HashMap<>();
|
||||
// fullname -> future contents that will be visible on close.
|
||||
Map<String, byte[]> futureContents = new HashMap<>();
|
||||
|
||||
private final boolean throwIfOption;
|
||||
|
||||
/** @param throwIfOption if true, we throw when given any option */
|
||||
public FakeStorageRpc(boolean throwIfOption) {
|
||||
this.throwIfOption = throwIfOption;
|
||||
}
|
||||
|
||||
// remove all files
|
||||
void reset() {
|
||||
metadata = new HashMap<>();
|
||||
contents = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageObject create(StorageObject object, InputStream content, Map<Option, ?> options)
|
||||
throws StorageException {
|
||||
potentiallyThrow(options);
|
||||
String key = fullname(object);
|
||||
object.setUpdated(now());
|
||||
metadata.put(key, object);
|
||||
try {
|
||||
contents.put(key, com.google.common.io.ByteStreams.toByteArray(content));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException(e);
|
||||
}
|
||||
// TODO: crc, etc
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tuple<String, Iterable<StorageObject>> list(String bucket, Map<Option, ?> options)
|
||||
throws StorageException {
|
||||
String delimiter = null;
|
||||
String preprefix = "";
|
||||
String pageToken = null;
|
||||
long maxResults = Long.MAX_VALUE;
|
||||
for (Map.Entry<Option, ?> e : options.entrySet()) {
|
||||
switch (e.getKey()) {
|
||||
case PAGE_TOKEN:
|
||||
pageToken = (String) e.getValue();
|
||||
break;
|
||||
case PREFIX:
|
||||
preprefix = (String) e.getValue();
|
||||
if (preprefix.startsWith("/")) {
|
||||
preprefix = preprefix.substring(1);
|
||||
}
|
||||
break;
|
||||
case DELIMITER:
|
||||
delimiter = (String) e.getValue();
|
||||
break;
|
||||
case FIELDS:
|
||||
// ignore and return all the fields
|
||||
break;
|
||||
case MAX_RESULTS:
|
||||
maxResults = (Long) e.getValue();
|
||||
break;
|
||||
case USER_PROJECT:
|
||||
// prevent unsupported operation
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown option: " + e.getKey());
|
||||
}
|
||||
}
|
||||
final String prefix = preprefix;
|
||||
|
||||
List<StorageObject> values = new ArrayList<>();
|
||||
Map<String, StorageObject> folders = new HashMap<>();
|
||||
for (StorageObject so : metadata.values()) {
|
||||
if (!so.getBucket().equals(bucket) || !so.getName().startsWith(prefix)) {
|
||||
continue;
|
||||
}
|
||||
if (processedAsFolder(so, delimiter, prefix, folders)) {
|
||||
continue;
|
||||
}
|
||||
so.setSize(size(so));
|
||||
values.add(so);
|
||||
}
|
||||
values.addAll(folders.values());
|
||||
|
||||
// truncate to max allowed length
|
||||
if (values.size() > maxResults) {
|
||||
List<StorageObject> newValues = new ArrayList<>();
|
||||
for (int i = 0; i < maxResults; i++) {
|
||||
newValues.add(values.get(i));
|
||||
}
|
||||
values = newValues;
|
||||
}
|
||||
|
||||
// null cursor to indicate there is no more data (empty string would cause us to be called
|
||||
// again).
|
||||
// The type cast seems to be necessary to help Java's typesystem remember that collections are
|
||||
// iterable.
|
||||
return Tuple.of(pageToken, (Iterable<StorageObject>) values);
|
||||
}
|
||||
|
||||
/** Returns the requested bucket or {@code null} if not found. */
|
||||
@Override
|
||||
public Bucket get(Bucket bucket, Map<Option, ?> options) throws StorageException {
|
||||
potentiallyThrow(options);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns the requested storage object or {@code null} if not found. */
|
||||
@Override
|
||||
public StorageObject get(StorageObject object, Map<Option, ?> options) throws StorageException {
|
||||
// we allow the "ID" option because we need to, but then we give a whole answer anyways
|
||||
// because the caller won't mind the extra fields.
|
||||
if (throwIfOption
|
||||
&& !options.isEmpty()
|
||||
&& options.size() > 1
|
||||
&& options.keySet().toArray()[0] != Storage.BlobGetOption.fields(Storage.BlobField.ID)) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
String key = fullname(object);
|
||||
if (metadata.containsKey(key)) {
|
||||
StorageObject ret = metadata.get(key);
|
||||
ret.setSize(size(ret));
|
||||
ret.setId(key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bucket patch(Bucket bucket, Map<Option, ?> options) throws StorageException {
|
||||
potentiallyThrow(options);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageObject patch(StorageObject storageObject, Map<Option, ?> options)
|
||||
throws StorageException {
|
||||
potentiallyThrow(options);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Bucket bucket, Map<Option, ?> options) throws StorageException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(StorageObject object, Map<Option, ?> options) throws StorageException {
|
||||
String key = fullname(object);
|
||||
contents.remove(key);
|
||||
return null != metadata.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageObject compose(
|
||||
Iterable<StorageObject> sources, StorageObject target, Map<Option, ?> targetOptions)
|
||||
throws StorageException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] load(StorageObject storageObject, Map<Option, ?> options) throws StorageException {
|
||||
String key = fullname(storageObject);
|
||||
if (!contents.containsKey(key)) {
|
||||
throw new StorageException(404, "File not found: " + key);
|
||||
}
|
||||
return contents.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tuple<String, byte[]> read(
|
||||
StorageObject from, Map<Option, ?> options, long zposition, int zbytes)
|
||||
throws StorageException {
|
||||
// if non-null, then we check the file's at that generation.
|
||||
Long generationMatch = null;
|
||||
for (Option op : options.keySet()) {
|
||||
if (op.equals(StorageRpc.Option.IF_GENERATION_MATCH)) {
|
||||
generationMatch = (Long) options.get(op);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown option: " + op);
|
||||
}
|
||||
}
|
||||
String key = fullname(from);
|
||||
if (!contents.containsKey(key)) {
|
||||
throw new StorageException(404, "File not found: " + key);
|
||||
}
|
||||
checkGeneration(key, generationMatch);
|
||||
long position = zposition;
|
||||
int bytes = zbytes;
|
||||
if (position < 0) {
|
||||
position = 0;
|
||||
}
|
||||
byte[] full = contents.get(key);
|
||||
if ((int) position + bytes > full.length) {
|
||||
bytes = full.length - (int) position;
|
||||
}
|
||||
if (bytes <= 0) {
|
||||
// special case: you're trying to read past the end
|
||||
return Tuple.of("etag-goes-here", new byte[0]);
|
||||
}
|
||||
byte[] ret = new byte[bytes];
|
||||
System.arraycopy(full, (int) position, ret, 0, bytes);
|
||||
return Tuple.of("etag-goes-here", ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long read(
|
||||
StorageObject from, Map<Option, ?> options, long position, OutputStream outputStream) {
|
||||
// if non-null, then we check the file's at that generation.
|
||||
Long generationMatch = null;
|
||||
for (Option op : options.keySet()) {
|
||||
if (op.equals(StorageRpc.Option.IF_GENERATION_MATCH)) {
|
||||
generationMatch = (Long) options.get(op);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown option: " + op);
|
||||
}
|
||||
}
|
||||
String key = fullname(from);
|
||||
if (!contents.containsKey(key)) {
|
||||
throw new StorageException(404, "File not found: " + key);
|
||||
}
|
||||
checkGeneration(key, generationMatch);
|
||||
if (position < 0) {
|
||||
position = 0;
|
||||
}
|
||||
byte[] full = contents.get(key);
|
||||
int bytes = (int) (full.length - position);
|
||||
if (bytes <= 0) {
|
||||
// special case: you're trying to read past the end
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
outputStream.write(full, (int) position, bytes);
|
||||
} catch (IOException e) {
|
||||
throw new StorageException(500, "Failed to write to file", e);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String open(StorageObject object, Map<Option, ?> options) throws StorageException {
|
||||
String key = fullname(object);
|
||||
// if non-null, then we check the file's at that generation.
|
||||
Long generationMatch = null;
|
||||
for (Option option : options.keySet()) {
|
||||
// this is a bit of a hack, since we don't implement generations.
|
||||
if (option == Option.IF_GENERATION_MATCH) {
|
||||
generationMatch = (Long) options.get(option);
|
||||
}
|
||||
}
|
||||
checkGeneration(key, generationMatch);
|
||||
metadata.put(key, object);
|
||||
|
||||
return fullname(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String open(String signedURL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(
|
||||
String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, int length, boolean last)
|
||||
throws StorageException {
|
||||
writeWithResponse(uploadId, toWrite, toWriteOffset, destOffset, length, last);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageObject writeWithResponse(
|
||||
String uploadId,
|
||||
byte[] toWrite,
|
||||
int toWriteOffset,
|
||||
long destOffset,
|
||||
int length,
|
||||
boolean last) {
|
||||
// this may have a lot more allocations than ideal, but it'll work.
|
||||
byte[] bytes;
|
||||
if (futureContents.containsKey(uploadId)) {
|
||||
bytes = futureContents.get(uploadId);
|
||||
if (bytes.length < length + destOffset) {
|
||||
byte[] newBytes = new byte[(int) (length + destOffset)];
|
||||
System.arraycopy(bytes, 0, newBytes, (int) 0, bytes.length);
|
||||
bytes = newBytes;
|
||||
}
|
||||
} else {
|
||||
bytes = new byte[(int) (length + destOffset)];
|
||||
}
|
||||
System.arraycopy(toWrite, toWriteOffset, bytes, (int) destOffset, length);
|
||||
// we want to mimic the GCS behavior that file contents are only visible on close.
|
||||
StorageObject storageObject = null;
|
||||
if (last) {
|
||||
contents.put(uploadId, bytes);
|
||||
futureContents.remove(uploadId);
|
||||
if (metadata.containsKey(uploadId)) {
|
||||
storageObject = metadata.get(uploadId);
|
||||
storageObject.setUpdated(now());
|
||||
Long generation = storageObject.getGeneration();
|
||||
if (null == generation) {
|
||||
generation = Long.valueOf(0);
|
||||
}
|
||||
storageObject.setGeneration(++generation);
|
||||
metadata.put(uploadId, storageObject);
|
||||
}
|
||||
} else {
|
||||
futureContents.put(uploadId, bytes);
|
||||
}
|
||||
return storageObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RewriteResponse openRewrite(RewriteRequest rewriteRequest) throws StorageException {
|
||||
String sourceKey = fullname(rewriteRequest.source);
|
||||
|
||||
// a little hackish, just good enough for the tests to work.
|
||||
if (!contents.containsKey(sourceKey)) {
|
||||
throw new StorageException(404, "File not found: " + sourceKey);
|
||||
}
|
||||
|
||||
// if non-null, then we check the file's at that generation.
|
||||
Long generationMatch = null;
|
||||
for (Option option : rewriteRequest.targetOptions.keySet()) {
|
||||
// this is a bit of a hack, since we don't implement generations.
|
||||
if (option == Option.IF_GENERATION_MATCH) {
|
||||
generationMatch = (Long) rewriteRequest.targetOptions.get(option);
|
||||
}
|
||||
}
|
||||
|
||||
String destKey = fullname(rewriteRequest.target);
|
||||
|
||||
// if this is a new file, set generation to 1, else increment the existing generation
|
||||
long generation = 1;
|
||||
if (metadata.containsKey(destKey)) {
|
||||
generation = metadata.get(destKey).getGeneration() + 1;
|
||||
}
|
||||
|
||||
checkGeneration(destKey, generationMatch);
|
||||
|
||||
byte[] data = contents.get(sourceKey);
|
||||
|
||||
rewriteRequest.target.setGeneration(generation);
|
||||
rewriteRequest.target.setSize(BigInteger.valueOf(data.length));
|
||||
rewriteRequest.target.setUpdated(metadata.get(sourceKey).getUpdated());
|
||||
|
||||
metadata.put(destKey, rewriteRequest.target);
|
||||
|
||||
contents.put(destKey, Arrays.copyOf(data, data.length));
|
||||
return new RewriteResponse(
|
||||
rewriteRequest,
|
||||
rewriteRequest.target,
|
||||
data.length,
|
||||
true,
|
||||
"rewriteToken goes here",
|
||||
data.length);
|
||||
}
|
||||
|
||||
private static DateTime now() {
|
||||
return DateTime.parseRfc3339(RFC_3339_FORMATTER.format(new Date()));
|
||||
}
|
||||
|
||||
private String fullname(StorageObject so) {
|
||||
return (so.getBucket() + "/" + so.getName());
|
||||
}
|
||||
|
||||
private BigInteger size(StorageObject so) {
|
||||
String key = fullname(so);
|
||||
|
||||
if (contents.containsKey(key)) {
|
||||
return BigInteger.valueOf(contents.get(key).length);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void potentiallyThrow(Map<Option, ?> options) throws UnsupportedOperationException {
|
||||
if (throwIfOption && !options.isEmpty()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw if we're asking for generation 0 and the file exists, or if the requested generation
|
||||
* number doesn't match what is asked.
|
||||
*
|
||||
* @param key
|
||||
* @param generationMatch
|
||||
*/
|
||||
private void checkGeneration(String key, Long generationMatch) {
|
||||
if (null == generationMatch) {
|
||||
return;
|
||||
}
|
||||
if (generationMatch == 0 && metadata.containsKey(key)) {
|
||||
throw new StorageException(new FileAlreadyExistsException(key));
|
||||
}
|
||||
if (generationMatch != 0) {
|
||||
Long generation = metadata.get(key).getGeneration();
|
||||
if (!generationMatch.equals(generation)) {
|
||||
throw new StorageException(
|
||||
404, "Generation mismatch. Requested " + generationMatch + " but got " + generation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if this is a folder. Adds it to folders if it isn't already there.
|
||||
private static boolean processedAsFolder(
|
||||
StorageObject so,
|
||||
String delimiter,
|
||||
String prefix, /* inout */
|
||||
Map<String, StorageObject> folders) {
|
||||
if (delimiter == null) {
|
||||
return false;
|
||||
}
|
||||
int nextSlash = so.getName().indexOf(delimiter, prefix.length());
|
||||
if (nextSlash < 0) {
|
||||
return false;
|
||||
}
|
||||
String folderName = so.getName().substring(0, nextSlash + 1);
|
||||
if (folders.containsKey(folderName)) {
|
||||
return true;
|
||||
}
|
||||
StorageObject fakeFolder = new StorageObject();
|
||||
fakeFolder.setName(folderName);
|
||||
fakeFolder.setBucket(so.getBucket());
|
||||
fakeFolder.setGeneration(so.getGeneration());
|
||||
fakeFolder.set("isDirectory", true);
|
||||
fakeFolder.setSize(BigInteger.ZERO);
|
||||
folders.put(folderName, fakeFolder);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceAccount getServiceAccount(String projectId) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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
|
||||
*
|
||||
* 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.gcs.backport;
|
||||
|
||||
import com.google.cloud.ServiceRpc;
|
||||
import com.google.cloud.spi.ServiceRpcFactory;
|
||||
import com.google.cloud.storage.StorageOptions;
|
||||
|
||||
/**
|
||||
* Utility to create an in-memory storage configuration for testing. Storage options can be obtained
|
||||
* via the {@link #getOptions()} method. Returned options will point to FakeStorageRpc.
|
||||
*
|
||||
* <p>Note, the created in-memory storage configuration supports limited set of operations and is
|
||||
* <b>not</b> thread-safe:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Supported operations
|
||||
* <ul>
|
||||
* <li>object create
|
||||
* <li>object get
|
||||
* <li>object delete
|
||||
* <li>list the contents of a bucket
|
||||
* </ul>
|
||||
* <li>Unsupported operations
|
||||
* <ul>
|
||||
* <li>bucket create
|
||||
* <li>bucket get
|
||||
* <li>bucket delete
|
||||
* <li>list all buckets
|
||||
* <li>generations
|
||||
* <li>file attributes
|
||||
* <li>patch
|
||||
* <li>continueRewrite
|
||||
* <li>createBatch
|
||||
* <li>checksums, etags
|
||||
* <li>IAM operations
|
||||
* </ul>
|
||||
* </ul>
|
||||
*
|
||||
* {@link FakeStorageRpc#list(String, java.util.Map)} lists all the objects that have been created
|
||||
* rather than the objects in the provided bucket. Since this class does not support creating,
|
||||
* listing and deleting buckets, the parameter bucket here is not actually used and on serves as a
|
||||
* placeholder.
|
||||
*/
|
||||
public final class LocalStorageHelper {
|
||||
|
||||
// used for testing. Will throw if you pass it an option.
|
||||
private static final FakeStorageRpc instance = new FakeStorageRpc(true);
|
||||
|
||||
private LocalStorageHelper() {}
|
||||
|
||||
/**
|
||||
* Returns a {@link StorageOptions} that use the static FakeStorageRpc instance, and resets it
|
||||
* first so you start from a clean slate. That instance will throw if you pass it any option.
|
||||
*/
|
||||
public static StorageOptions getOptions() {
|
||||
instance.reset();
|
||||
return StorageOptions.newBuilder()
|
||||
.setProjectId("fake-project-for-testing")
|
||||
.setServiceRpcFactory(new FakeStorageRpcFactory())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link StorageOptions} that creates a new FakeStorageRpc instance with the given
|
||||
* option.
|
||||
*/
|
||||
public static StorageOptions customOptions(final boolean throwIfOptions) {
|
||||
return StorageOptions.newBuilder()
|
||||
.setProjectId("fake-project-for-testing")
|
||||
.setServiceRpcFactory(new FakeStorageRpcFactory(new FakeStorageRpc(throwIfOptions)))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class FakeStorageRpcFactory implements ServiceRpcFactory<StorageOptions> {
|
||||
|
||||
private final FakeStorageRpc instance;
|
||||
|
||||
public FakeStorageRpcFactory() {
|
||||
this(LocalStorageHelper.instance);
|
||||
}
|
||||
|
||||
public FakeStorageRpcFactory(FakeStorageRpc instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceRpc create(StorageOptions storageOptions) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
The files here are directly lifted
|
||||
from [googleapis/java-storage-nio](https://github.com/googleapis/java-storage-nio/tree/master/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing)
|
||||
. They are needed because the `StorageOptions` returned from `LocalStorageHelper.getOptions()`
|
||||
should be serializable for the `GcsUtils` class itself to be serializable in tests, but is not. The
|
||||
bug is [fixed](https://github.com/googleapis/java-storage-nio/pull/606) upstream. However, the
|
||||
current released package does not contain the fix yet.
|
||||
|
||||
They are not put under `common/testing` because we do not want to introduce a dependency on the
|
||||
testing configuration from core.
|
|
@ -21,11 +21,11 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.common.io.Files;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.BouncyCastleProviderExtension;
|
||||
|
|
|
@ -40,11 +40,11 @@ import com.google.appengine.api.urlfetch.HTTPRequest;
|
|||
import com.google.appengine.api.urlfetch.HTTPResponse;
|
||||
import com.google.appengine.api.urlfetch.URLFetchService;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.ByteSource;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registry.Registry;
|
||||
|
|
|
@ -35,12 +35,12 @@ import static java.util.Arrays.asList;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import google.registry.keyring.api.PgpHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
|
|
|
@ -29,10 +29,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
import com.google.appengine.tools.mapreduce.ReducerInput;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.StorageException;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.beam.rde.RdePipelineTest;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.keyring.api.PgpHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
|
|
|
@ -44,6 +44,7 @@ import static org.mockito.Mockito.when;
|
|||
import com.google.appengine.api.taskqueue.QueueFactory;
|
||||
import com.google.appengine.api.utils.SystemProperty;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.common.io.Files;
|
||||
|
@ -51,7 +52,6 @@ import com.jcraft.jsch.JSch;
|
|||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.keyring.api.Keyring;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
|
|
|
@ -29,9 +29,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import com.google.api.services.bigquery.model.TableFieldSchema;
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
@ -29,7 +30,6 @@ import google.registry.bigquery.BigqueryConnection;
|
|||
import google.registry.bigquery.BigqueryConnection.DestinationTable;
|
||||
import google.registry.bigquery.BigqueryUtils.TableType;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.reporting.icann.IcannReportingModule.ReportType;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeResponse;
|
||||
|
|
|
@ -29,9 +29,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.testing.TestLogHandler;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.registry.Registry;
|
||||
|
|
|
@ -27,12 +27,12 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||
import static org.joda.time.Duration.standardDays;
|
||||
|
||||
import com.google.cloud.storage.BlobId;
|
||||
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.gcs.backport.LocalStorageHelper;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue