Skip to content

Commit

Permalink
Support Nessie Catalog in Iceberg connector
Browse files Browse the repository at this point in the history
This PR integrates the (Nessie catalog functionality)[https://github.com/apache/iceberg/tree/master/nessie/src/main/java/org/apache/iceberg/nessie] to the Iceberg connector. It adds the following new things:

* a new `CatalogType` called `NESSIE`
* an `IcebergNessieCatalogModule` that sets up all necessary dependencies (including a client to connect to the Nessie server)
* a `NessieConfig` that includes configuration settings required for Nessie
* `TrinoNessieCatalog` + `NessieIcebergTableOperations` that implement the main behavior of the catalog
* some unit and integration tests that verify that the Iceberg connector works with Nessie (note that the integration test requires a Nessie server to be started, which is being done via the `nessie-apprunner-maven-plugin`prior to the integration-test phase)

This PR does not yet include documentation updates, as I'd like to get some feedback first before addressing that.
  • Loading branch information
nastra committed Mar 29, 2022
1 parent b89a7c9 commit 66fed2e
Show file tree
Hide file tree
Showing 14 changed files with 1,412 additions and 0 deletions.
89 changes: 89 additions & 0 deletions plugin/trino-iceberg/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<properties>
<air.main.basedir>${project.parent.basedir}</air.main.basedir>
<dep.iceberg.version>0.13.1</dep.iceberg.version>
<dep.nessie.version>0.23.1</dep.nessie.version>
<dep.nessie-apprunner.version>0.21.4</dep.nessie-apprunner.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -187,6 +189,18 @@
</exclusions>
</dependency>

<dependency>
<groupId>org.projectnessie</groupId>
<artifactId>nessie-client</artifactId>
<version>${dep.nessie.version}</version>
</dependency>

<dependency>
<groupId>org.projectnessie</groupId>
<artifactId>nessie-model</artifactId>
<version>${dep.nessie.version}</version>
</dependency>

<dependency>
<groupId>org.weakref</groupId>
<artifactId>jmxutils</artifactId>
Expand Down Expand Up @@ -353,6 +367,64 @@
</ignoredResourcePatterns>
</configuration>
</plugin>
<plugin>
<groupId>org.projectnessie</groupId>
<artifactId>nessie-apprunner-maven-plugin</artifactId>
<version>${dep.nessie-apprunner.version}</version>
<configuration>
<skip>${skipITs}</skip>
<appArtifactId>org.projectnessie:nessie-quarkus:jar:runner:${dep.nessie.version}</appArtifactId>
<systemProperties>
<!-- disable devservices to stop Quarkus from starting Mongo via testcontainers -->
<quarkus.devservices.enabled>false</quarkus.devservices.enabled>
<!-- Use INMEMORY version store for testing -->
<nessie.version.store.type>INMEMORY</nessie.version.store.type>
</systemProperties>
</configuration>
<dependencies>
<dependency>
<groupId>org.projectnessie</groupId>
<artifactId>nessie-quarkus</artifactId>
<version>${dep.nessie.version}</version>
<classifier>runner</classifier>
</dependency>
</dependencies>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals><goal>start</goal></goals>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals><goal>stop</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<systemPropertyVariables>
<!-- this automatically injects the random port that the nessie server is using -->
<nessie.http.test-port>${quarkus.http.test-port}</nessie.http.test-port>
</systemPropertyVariables>
<failIfNoTests>false</failIfNoTests>
<includes>
<include>**/TestTrinoNessieCatalogIntegration.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand All @@ -374,6 +446,7 @@
<exclude>**/TestTrinoGlueCatalogTest.java</exclude>
<exclude>**/TestSharedGlueMetastore.java</exclude>
<exclude>**/TestIcebergGlueCatalogAccessOperations.java</exclude>
<exclude>**/TestTrinoNessieCatalogIntegration.java</exclude>
</excludes>
</configuration>
</plugin>
Expand Down Expand Up @@ -419,5 +492,21 @@
</plugins>
</build>
</profile>
<profile>
<id>nessie</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/Test*Nessie*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ public enum CatalogType
TESTING_FILE_METASTORE,
HIVE_METASTORE,
GLUE,
NESSIE,
/**/;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@
import io.trino.plugin.iceberg.catalog.glue.IcebergGlueCatalogModule;
import io.trino.plugin.iceberg.catalog.hms.IcebergHiveMetastoreCatalogModule;
import io.trino.plugin.iceberg.catalog.hms.TrinoHiveCatalogFactory;
import io.trino.plugin.iceberg.catalog.nessie.IcebergNessieCatalogModule;

import java.util.Optional;

import static io.airlift.configuration.ConditionalModule.conditionalModule;
import static io.trino.plugin.iceberg.CatalogType.GLUE;
import static io.trino.plugin.iceberg.CatalogType.HIVE_METASTORE;
import static io.trino.plugin.iceberg.CatalogType.NESSIE;
import static io.trino.plugin.iceberg.CatalogType.TESTING_FILE_METASTORE;
import static java.util.Objects.requireNonNull;

Expand Down Expand Up @@ -63,6 +65,7 @@ protected void setup(Binder binder)
bindCatalogModule(HIVE_METASTORE, new IcebergHiveMetastoreCatalogModule());
bindCatalogModule(TESTING_FILE_METASTORE, new IcebergFileMetastoreCatalogModule());
bindCatalogModule(GLUE, new IcebergGlueCatalogModule());
bindCatalogModule(NESSIE, new IcebergNessieCatalogModule());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 io.trino.plugin.iceberg.catalog.nessie;

import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Scopes;
import io.airlift.configuration.AbstractConfigurationAwareModule;
import io.trino.plugin.iceberg.catalog.IcebergTableOperationsProvider;
import io.trino.plugin.iceberg.catalog.TrinoCatalogFactory;
import org.projectnessie.client.api.NessieApiV1;
import org.projectnessie.client.http.HttpClientBuilder;

import javax.inject.Provider;

import static io.airlift.configuration.ConfigBinder.configBinder;
import static org.weakref.jmx.guice.ExportBinder.newExporter;

public class IcebergNessieCatalogModule
extends AbstractConfigurationAwareModule
{
@Override
protected void setup(Binder binder)
{
configBinder(binder).bindConfig(NessieConfig.class);
binder.bind(UpdateableReference.class);
binder.bind(NessieApiV1.class).toProvider(NessieApiProvider.class).in(Scopes.SINGLETON);
binder.bind(IcebergTableOperationsProvider.class).to(NessieIcebergTableOperationsProvider.class).in(Scopes.SINGLETON);
newExporter(binder).export(IcebergTableOperationsProvider.class).withGeneratedName();
binder.bind(TrinoCatalogFactory.class).to(TrinoNessieCatalogFactory.class).in(Scopes.SINGLETON);
newExporter(binder).export(TrinoCatalogFactory.class).withGeneratedName();
}

public static class NessieApiProvider
implements Provider<NessieApiV1>
{
private final NessieConfig nessieConfig;

@Inject
public NessieApiProvider(NessieConfig nessieConfig)
{
this.nessieConfig = nessieConfig;
}

@Override
public NessieApiV1 get()
{
return HttpClientBuilder.builder()
.withUri(nessieConfig.getServerUri())
.build(NessieApiV1.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 io.trino.plugin.iceberg.catalog.nessie;

import io.airlift.configuration.Config;
import io.airlift.configuration.ConfigDescription;

import javax.validation.constraints.NotEmpty;

public class NessieConfig
{
private String defaultReferenceName = "main";
private String serverUri = "http://localhost:19120/api/v1";
private String warehouseDir;

public String getDefaultReferenceName()
{
return defaultReferenceName;
}

@Config("iceberg.nessie.ref")
@ConfigDescription("The default Nessie reference to work on")
public NessieConfig setDefaultReferenceName(String defaultReferenceName)
{
this.defaultReferenceName = defaultReferenceName;
return this;
}

public String getServerUri()
{
return serverUri;
}

@Config("iceberg.nessie.uri")
@ConfigDescription("The URI to connect to the Nessie server")
public NessieConfig setServerUri(String serverUri)
{
this.serverUri = serverUri;
return this;
}

@NotEmpty
public String getWarehouseDir()
{
return warehouseDir;
}

@Config("iceberg.nessie.warehouse")
@ConfigDescription("The default warehouse to use for Nessie")
public NessieConfig setWarehouseDir(String warehouseDir)
{
this.warehouseDir = warehouseDir;
return this;
}
}
Loading

0 comments on commit 66fed2e

Please sign in to comment.