Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ public enum ClientError implements ScalarDlError {
"The specified keys are incorrect for the asset type.",
"",
""),
SERVICE_NAMESPACE_NAME_CANNOT_BE_NULL(
StatusCode.INVALID_ARGUMENT, "025", "The namespace name cannot be null.", "", ""),

//
// Errors for RUNTIME_ERROR(502)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.ExecutionOrderingResponse;
import com.scalar.dl.rpc.ExecutionValidationRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import io.grpc.ManagedChannel;
import io.grpc.netty.NettyChannelBuilder;
Expand Down Expand Up @@ -137,6 +138,17 @@ public ContractExecutionResponse validate(ExecutionValidationRequest request) {
return ContractExecutionResponse.getDefaultInstance();
}

@Override
public void create(NamespaceCreationRequest request) {
ThrowableConsumer<NamespaceCreationRequest> f =
r -> getAuditorPrivilegedStub().createNamespace(r);
try {
accept(f, request);
} catch (Exception e) {
throwExceptionWithStatusCode(e);
}
}

private AuditorGrpc.AuditorBlockingStub getAuditorStub() {
return auditorStub.withDeadlineAfter(deadlineDurationMillis, TimeUnit.MILLISECONDS);
}
Expand Down
3 changes: 3 additions & 0 deletions client/src/main/java/com/scalar/dl/client/service/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.scalar.dl.rpc.CertificateRegistrationRequest;
import com.scalar.dl.rpc.ContractRegistrationRequest;
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import com.scalar.dl.rpc.Status;
import io.grpc.Metadata;
Expand All @@ -29,6 +30,8 @@ public interface Client {

JsonObject list(ContractsListingRequest request);

void create(NamespaceCreationRequest request);

default <T> void accept(ThrowableConsumer<T> f, T request) {
try {
f.accept(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.FunctionRegistrationRequest;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -985,6 +986,41 @@ public LedgerValidationResult validateLedger(byte[] serializedBinary) {
return handler.validateLedger(request);
}

/**
* Creates the specified namespace.
*
* @param namespace a namespace name to create
* @throws ClientException if a request fails for some reason
*/
public void createNamespace(String namespace) {
checkClientMode(ClientMode.CLIENT);
checkArgument(
namespace != null, ClientError.SERVICE_NAMESPACE_NAME_CANNOT_BE_NULL.buildMessage());
NamespaceCreationRequest request =
NamespaceCreationRequest.newBuilder().setNamespace(namespace).build();

handler.createNamespace(request);
}

/**
* Creates the namespace specified with the serialized byte array of a {@code
* NamespaceCreationRequest}.
*
* @param serializedBinary a serialized byte array of {@code NamespaceCreationRequest}
* @throws ClientException if a request fails for some reason
*/
public void createNamespace(byte[] serializedBinary) {
checkClientMode(ClientMode.INTERMEDIARY);
NamespaceCreationRequest request;
try {
request = NamespaceCreationRequest.parseFrom(serializedBinary);
} catch (InvalidProtocolBufferException e) {
throw new IllegalArgumentException(e.getMessage(), e);
}

handler.createNamespace(request);
}

/**
* It does nothing now. It's left here for backward compatibility.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.FunctionRegistrationRequest;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import javax.json.JsonObject;

Expand Down Expand Up @@ -74,4 +75,6 @@ public interface ClientServiceHandler {
* @throws ClientException if a request fails for some reason
*/
LedgerValidationResult validateLedger(LedgerValidationRequest request);

void createNamespace(NamespaceCreationRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.scalar.dl.rpc.ExecutionValidationRequest;
import com.scalar.dl.rpc.FunctionRegistrationRequest;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -128,6 +129,12 @@ public LedgerValidationResult validateLedger(LedgerValidationRequest request) {
return client.validate(request);
}

@Override
public void createNamespace(NamespaceCreationRequest request) {
createAtAuditor(request);
client.create(request);
}

private void registerToAuditor(CertificateRegistrationRequest request) {
if (auditorClient == null) {
return;
Expand Down Expand Up @@ -167,6 +174,19 @@ private void registerToAuditor(ContractRegistrationRequest request) {
}
}

private void createAtAuditor(NamespaceCreationRequest request) {
if (auditorClient == null) {
return;
}
try {
auditorClient.create(request);
} catch (ClientException e) {
if (!e.getStatusCode().equals(StatusCode.NAMESPACE_ALREADY_EXISTS)) {
throw e;
}
}
}

private ContractExecutionRequest order(ContractExecutionRequest request) {
if (auditorClient == null) {
return request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.scalar.dl.rpc.GatewayPrivilegedGrpc;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.LedgerValidationResponse;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import io.grpc.ManagedChannel;
import io.grpc.netty.NettyChannelBuilder;
Expand Down Expand Up @@ -183,6 +184,17 @@ public LedgerValidationResult validate(LedgerValidationRequest request) {
return new LedgerValidationResult(StatusCode.RUNTIME_ERROR, null, null);
}

@Override
public void create(NamespaceCreationRequest request) {
ThrowableConsumer<NamespaceCreationRequest> f =
r -> getGatewayPrivilegedStub().createNamespace(r);
try {
accept(f, request);
} catch (Exception e) {
throwExceptionWithStatusCode(e);
}
}

private GatewayGrpc.GatewayBlockingStub getGatewayStub() {
return gatewayStub.withDeadlineAfter(deadlineDurationMillis, TimeUnit.MILLISECONDS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.FunctionRegistrationRequest;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import javax.json.JsonObject;

Expand Down Expand Up @@ -108,6 +109,11 @@ public LedgerValidationResult validateLedger(LedgerValidationRequest request) {
return client.validate(request);
}

@Override
public void createNamespace(NamespaceCreationRequest request) {
client.create(request);
}

@VisibleForTesting
AbstractGatewayClient getGatewayClient() {
return client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.scalar.dl.rpc.LedgerPrivilegedGrpc;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.LedgerValidationResponse;
import com.scalar.dl.rpc.NamespaceCreationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import io.grpc.ManagedChannel;
import io.grpc.netty.NettyChannelBuilder;
Expand Down Expand Up @@ -230,6 +231,17 @@ public TransactionState abort(ExecutionAbortRequest request) {
return TransactionState.UNKNOWN;
}

@Override
public void create(NamespaceCreationRequest request) {
ThrowableConsumer<NamespaceCreationRequest> f =
r -> getLedgerPrivilegedStub().createNamespace(r);
try {
accept(f, request);
} catch (Exception e) {
throwExceptionWithStatusCode(e);
}
}

private LedgerGrpc.LedgerBlockingStub getLedgerStub() {
return ledgerStub.withDeadlineAfter(deadlineDurationMillis, TimeUnit.MILLISECONDS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -724,4 +724,95 @@ public void validateLedger_SerializedBinaryGiven_ShouldValidateProperly() {
verify(config, never()).getHmacIdentityConfig();
verify(signer, never()).sign(any(LedgerValidationRequest.Builder.class));
}

@Test
public void createNamespace_CorrectInputsGiven_ShouldCreateNamespaceProperly() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.CLIENT);
String namespace = "test_namespace";

// Act
service.createNamespace(namespace);

// Assert
com.scalar.dl.rpc.NamespaceCreationRequest expected =
com.scalar.dl.rpc.NamespaceCreationRequest.newBuilder().setNamespace(namespace).build();
verify(handler).createNamespace(expected);
}

@Test
public void createNamespace_NullNamespaceGiven_ShouldThrowIllegalArgumentException() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.CLIENT);

// Act
Throwable thrown = catchThrowable(() -> service.createNamespace((String) null));

// Assert
assertThat(thrown).isExactlyInstanceOf(IllegalArgumentException.class);
verify(handler, never()).createNamespace(any(com.scalar.dl.rpc.NamespaceCreationRequest.class));
}

@Test
public void
createNamespace_NamespaceNameWithIntermediaryModeGiven_ShouldThrowIllegalArgumentException() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.INTERMEDIARY);
String namespace = "test_namespace";

// Act
Throwable thrown = catchThrowable(() -> service.createNamespace(namespace));

// Assert
assertThat(thrown).isExactlyInstanceOf(IllegalArgumentException.class);
verify(handler, never()).createNamespace(any(com.scalar.dl.rpc.NamespaceCreationRequest.class));
}

@Test
public void createNamespace_SerializedBinaryGiven_ShouldCreateNamespaceProperly() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.INTERMEDIARY);
com.scalar.dl.rpc.NamespaceCreationRequest expected =
com.scalar.dl.rpc.NamespaceCreationRequest.newBuilder()
.setNamespace("test_namespace")
.build();

// Act
service.createNamespace(expected.toByteArray());

// Assert
verify(handler).createNamespace(expected);
}

@Test
public void createNamespace_InvalidSerializedBinaryGiven_ShouldThrowIllegalArgumentException() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.INTERMEDIARY);
byte[] invalidBinary = "invalid".getBytes(StandardCharsets.UTF_8);

// Act
Throwable thrown = catchThrowable(() -> service.createNamespace(invalidBinary));

// Assert
assertThat(thrown).isExactlyInstanceOf(IllegalArgumentException.class);
verify(handler, never()).createNamespace(any(com.scalar.dl.rpc.NamespaceCreationRequest.class));
}

@Test
public void
createNamespace_SerializedBinaryClientModeGiven_ShouldThrowIllegalArgumentException() {
// Arrange
when(config.getClientMode()).thenReturn(ClientMode.CLIENT);
com.scalar.dl.rpc.NamespaceCreationRequest request =
com.scalar.dl.rpc.NamespaceCreationRequest.newBuilder()
.setNamespace("test_namespace")
.build();

// Act
Throwable thrown = catchThrowable(() -> service.createNamespace(request.toByteArray()));

// Assert
assertThat(thrown).isExactlyInstanceOf(IllegalArgumentException.class);
verify(handler, never()).createNamespace(any(com.scalar.dl.rpc.NamespaceCreationRequest.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public interface ServerConfig {

String getName();

String getNamespace();

int getPort();

int getPrivilegedPort();
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/com/scalar/dl/ledger/error/CommonError.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,25 @@ public enum CommonError implements ScalarDlError {
"The deserialization type is not supported. Type: %s",
"",
""),
INVALID_NAMESPACE_NAME(
StatusCode.INVALID_ARGUMENT, "019", "The namespace name is invalid. Name: %s", "", ""),

//
// Errors for SECRET_NOT_FOUND(415)
//
SECRET_NOT_FOUND(
StatusCode.SECRET_NOT_FOUND, "001", "The specified secret is not found.", "", ""),

//
// Errors for NAMESPACE_ALREADY_EXISTS(416)
//
NAMESPACE_ALREADY_EXISTS(
StatusCode.NAMESPACE_ALREADY_EXISTS,
"001",
"The specified namespace already exists.",
"",
""),

//
// Errors for DATABASE_ERROR(500)
//
Expand All @@ -241,6 +253,10 @@ public enum CommonError implements ScalarDlError {
StatusCode.DATABASE_ERROR, "008", "Getting the contract failed. Details: %s", "", ""),
SCANNING_CONTRACT_FAILED(
StatusCode.DATABASE_ERROR, "009", "Scanning the contracts failed. Details: %s", "", ""),
CREATING_NAMESPACE_TABLE_FAILED(
StatusCode.DATABASE_ERROR, "010", "Creating the namespace table failed. Details: %s", "", ""),
CREATING_NAMESPACE_FAILED(
StatusCode.DATABASE_ERROR, "011", "Creating the namespace failed. Details: %s", "", ""),

//
// Errors for RUNTIME_ERROR(502)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public LedgerException(ScalarDlError error, Object... args) {
this(error.buildMessage(args), error.getStatusCode());
}

public LedgerException(ScalarDlError error, Throwable cause, Object... args) {
this(error.buildMessage(args), cause, error.getStatusCode());
}

public StatusCode getCode() {
return code;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ private io.grpc.Status convert(StatusCode code) {
case CERTIFICATE_ALREADY_REGISTERED:
case SECRET_ALREADY_REGISTERED:
case CONTRACT_ALREADY_REGISTERED:
case NAMESPACE_ALREADY_EXISTS:
return io.grpc.Status.ALREADY_EXISTS;
case UNAVAILABLE:
return io.grpc.Status.UNAVAILABLE;
Expand Down
Loading