Skip to content
Closed
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
@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.iceberg.exceptions;

/**
* Exception raised when an attempt to perform an operation fails due to invalid permissions.
*/
public class NotAuthorizedException extends RuntimeException {
public NotAuthorizedException(String message) {
super(message);
}

public NotAuthorizedException(String message, Object... args) {
super(String.format(message, args));
}

public NotAuthorizedException(String message, Throwable cause) {
super(message, cause);
}
}
101 changes: 101 additions & 0 deletions api/src/main/java/org/apache/iceberg/rest/CreateNamespaceRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.iceberg.rest;

import java.util.Map;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;

/**
* Represents a REST request to create a namespace / database.
*
* Possible example POST body (outer format object possibly only used on Response):
* { "data": { "namespace": ["prod", "accounting"], properties: {} }}
Copy link
Contributor Author

@kbendick kbendick Nov 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently it's actually as follows, without using an array for Namespace.

{ "namespace": "prod.accounting", "properties": { "key1": "value1" } }

Now that I have the mock server going, I'm going to enter an OpenAPI spec and then run the tests over the spec (as I've done for a create namespace based one).

Will put the spec in this PR as a separate document.

*/
public class CreateNamespaceRequest {

private Namespace namespace;
private Map<String, String> properties;

private CreateNamespaceRequest() {
}

private CreateNamespaceRequest(String[] namespaceLevels, Map<String, String> properties) {
this.namespace = Namespace.of(namespaceLevels);
this.properties = properties;
}

public Namespace getNamespace() {
return namespace;
}

public void setNamespace(Namespace namespace) {
this.namespace = namespace;
}

public Map<String, String> getProperties() {
return properties;
}

public void setProperties(Map<String, String> properties) {
this.properties = properties;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private ImmutableList.Builder<String> namespaceBuilder;
private final ImmutableMap.Builder<String, String> propertiesBuilder;

public Builder() {
this.namespaceBuilder = ImmutableList.builder();
this.propertiesBuilder = ImmutableMap.builder();
}

public Builder withNamespace(Namespace namespace) {
this.namespaceBuilder.add(namespace.levels());
return this;
}

public Builder withProperties(Map<String, String> properties) {
if (properties != null) {
propertiesBuilder.putAll(properties);
}
return this;
}

public Builder withProperty(String key, String value) {
propertiesBuilder.put(key, value);
return this;
}

public CreateNamespaceRequest build() {
String[] namespaceLevels = namespaceBuilder.build().toArray(new String[0]);
Preconditions.checkState(namespaceLevels.length > 0,
"Cannot create a CreateNamespaceRequest with an empty namespace.");
return new CreateNamespaceRequest(namespaceLevels, propertiesBuilder.build());

}
}
}
120 changes: 120 additions & 0 deletions api/src/main/java/org/apache/iceberg/rest/CreateNamespaceResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.iceberg.rest;

import java.util.Map;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;

/**
* Represents a REST response to a create a namespace / database request.
*
* The properties returned will include all the user provided properties from the
* request, as well as any server-side added properties.
*
* Example server-side added properties could include things such as "created-at"
* or "owner".
*
* Presently, the JSON looks as follows:
* { "namespace": "ns1.ns2.ns3", "properties": { "owner": "hank", "created-at": "1425744000000" } }
*
* Eventually, the idea is to wrap responses in IcebergHttpResponse so that it has a more standardized
* structure, including the possibility of richer metadata on errors, such as tracing telemetry or follw
* up user instruction.
*
* {
Copy link
Contributor

@jackye1995 jackye1995 Nov 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need <pre> HTML tag for these code blocks to show properly in javadoc.

* "error": { },
* "data": {
* "namespace": "ns1.ns2.ns3",
* "properties": {
* "owner": "hank",
* "created-at": "1425744000000"
* }
* }
* }
*
* For an error response, we'll see something like the following:
*
* {
* "data": { },
* "error": {
* "message": "Namespace already exists",
* "type": "AlreadyExistsException",
* "code": 40901
* }
* }
*/
public class CreateNamespaceResponse {
private Namespace namespace;
private Map<String, String> properties;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the properties that the namespace has after create? For example, this may include a "created-at" property that was added by the server automatically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that was my thinking (about server side additions). I was thinking that this would be either:

  1. Properties the server added, such as created-at.
  2. The entire properties of the namespace, including the ones the user provided, to give a full picture.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I meant #2. All properties of the namespace, including the ones the user sent and the ones that were added automatically. We should document this in the class Javadoc.


private CreateNamespaceResponse() {
}

private CreateNamespaceResponse(Namespace namespace, Map<String, String> properties) {
this.namespace = namespace;
this.properties = properties;
}

public Namespace getNamespace() {
return namespace;
}

public void setNamespace(Namespace namespace) {
this.namespace = namespace;
}

public Map<String, String> getProperties() {
return properties;
}

public void setProperties(Map<String, String> properties) {
this.properties = properties;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private Namespace namespace;
private Map<String, String> properties;

private Builder() {

}

public Builder withNamespace(Namespace ns) {
this.namespace = ns;
return this;
}

public Builder withProperties(Map<String, String> props) {
this.properties = props;
return this;
}

public CreateNamespaceResponse build() {
Preconditions.checkArgument(namespace != null && !namespace.isEmpty(),
"Cannot create a CreateNamespaceResponse with a null or empty namespace");
return new CreateNamespaceResponse(namespace, properties);
}
}
}
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ subprojects {
testImplementation 'org.slf4j:slf4j-simple'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.mock-server:mockserver-junit-jupiter'
testImplementation 'org.mock-server:mockserver-netty'
testImplementation 'org.mock-server:mockserver-client-java'
}

test {
Expand Down Expand Up @@ -221,6 +224,8 @@ project(':iceberg-core') {
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
}

implementation 'org.apache.httpcomponents.client5:httpclient5'

testImplementation "org.xerial:sqlite-jdbc"
testImplementation project(path: ':iceberg-api', configuration: 'testArtifacts')
}
Expand Down
Loading