Skip to content

Commit

Permalink
Cleanup nessie-client (#7516)
Browse files Browse the repository at this point in the history
Cleanup the packages and especially the public facing client API and enhance the ability to configure a Nessie client instance.

`NessieClientBuilder` related changes:

* Use Java system properties, process environment, a (new) Nessie client config file and a dot-env file as configuration sources. Can later be extended to allow encrypted configuration values (think: bearer tokens, passwords, etc) and expressions by using SmallRye Config.
* Refactor `NessieClientBuilder` to use the Java services API, so it's easier to pull in custom implementations.
* Make `NessieClientBuilder` a "pure interface", add abstract base class(es) for implementations.
* Remove the generic type arg from `NessieClientBuilder`, because it's irrelevant for integrations, added a generic `asInstanceOf()` for special cases.
* Move configuration via string key-value pairs (`fromConfig()` functions) to the introduced abstract base classes.

Nessie API implementation related changes:

* Move REST/API-v1 code to the new `org.projectnessie.client.rest.v1` package.
* Move REST/API-v2 code to the new `org.projectnessie.client.rest.v2` package.
* Let the `org.projectnessie.client.http` itself only contain types for HTTP, except the legacy `HttpClientBuilder`, which is now deprecated for removal.
* Remove old, Java streams related baggage (restricts compatibility tests to 0.31.0 or newer).
* Move "common" client-side namsepace handling out of the REST-v2 implementation.
* Fix an oversight in the REST-v2 implementation for tag deletion.

Content-generator tool change:

* Add option for Nessie client name
* Add option for Nessie client builder properties

GC tool change:

* Add option for Nessie client name

Test support change:

* add `NessieClientNameResolver` interface for test classes
  • Loading branch information
snazy authored Sep 20, 2023
1 parent 91ca867 commit 81b34b6
Show file tree
Hide file tree
Showing 104 changed files with 2,220 additions and 1,089 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ jobs:
ICEBERG_MAIN_REPOSITORY: apache/iceberg
ICEBERG_MAIN_BRANCH: master
ICEBERG_PATCH_REPOSITORY: snazy/iceberg
ICEBERG_PATCH_BRANCH: iceberg-nesqueit
ICEBERG_PATCH_BRANCH: iceberg-nesqueit-next
SPARK_LOCAL_IP: localhost
steps:
- name: Prepare Git
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public URI resolve(URI base) {
return base.resolve(getPathElement());
}

public NessieApiV1 build(NessieClientBuilder<?> builder) {
public NessieApiV1 build(NessieClientBuilder builder) {
return builder.build(clientApiClass);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@
@FunctionalInterface
public interface NessieClientCustomizer {

NessieClientBuilder<?> configure(NessieClientBuilder<?> builder, NessieApiVersion apiVersion);
NessieClientBuilder configure(NessieClientBuilder builder, NessieApiVersion apiVersion);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 Dremio
*
* 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 org.projectnessie.client.ext;

import java.util.HashMap;
import java.util.Map;
import org.projectnessie.client.NessieClientBuilder;
import org.projectnessie.client.NessieConfigConstants;

/**
* Test classes that implement this interface can specify a different Nessie client by {@linkplain
* NessieClientBuilder#name() its name} and optionally a set of configuration options.
*/
@FunctionalInterface
public interface NessieClientNameResolver {
String nessieClientName();

/**
* When overriding this function, make sure to use the map of this implementation to include the
* {@link #nessieClientName()}.
*/
default Map<String, String> mainNessieClientConfigMap() {
Map<String, String> mainConfig = new HashMap<>();
mainConfig.put(NessieConfigConstants.CONF_NESSIE_CLIENT_NAME, nessieClientName());
return mainConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.projectnessie.client.ext;

import static org.projectnessie.client.NessieClientBuilder.createClientBuilderFromSystemSettings;
import static org.projectnessie.client.ext.MultiVersionApiTest.apiVersion;

import java.io.Serializable;
Expand All @@ -30,8 +31,10 @@
import org.junit.platform.commons.util.AnnotationUtils;
import org.projectnessie.client.NessieClientBuilder;
import org.projectnessie.client.api.NessieApiV1;
import org.projectnessie.client.http.HttpClientBuilder;
import org.projectnessie.client.config.NessieClientConfigSource;
import org.projectnessie.client.config.NessieClientConfigSources;
import org.projectnessie.client.http.HttpResponseFactory;
import org.projectnessie.client.http.NessieHttpClientBuilder;

/**
* A base class for extensions that manage a Nessie test execution environment. This class injects
Expand Down Expand Up @@ -89,6 +92,15 @@ public Object resolveParameter(
}

private NessieClientFactory clientFactoryForContext(ExtensionContext extensionContext) {
NessieClientConfigSource mainConfigSource =
extensionContext
.getTestInstance()
.filter(t -> t instanceof NessieClientNameResolver)
.map(NessieClientNameResolver.class::cast)
.map(NessieClientNameResolver::mainNessieClientConfigMap)
.map(NessieClientConfigSources::mapConfigSource)
.orElseGet(NessieClientConfigSources::emptyConfigSource);

NessieApiVersion apiVersion = apiVersion(extensionContext);
URI uri = resolvedNessieUri(extensionContext);
List<NessieClientCustomizer> customizers =
Expand Down Expand Up @@ -118,7 +130,7 @@ private NessieClientFactory clientFactoryForContext(ExtensionContext extensionCo
return builder;
};

return new ClientFactory(uri, apiVersion, responseFactoryClass) {
return new ClientFactory(uri, mainConfigSource, apiVersion, responseFactoryClass) {
@Nonnull
@jakarta.annotation.Nonnull
@Override // Note: this object is not serializable
Expand All @@ -132,19 +144,23 @@ public NessieApiV1 make(NessieClientCustomizer customizer) {

// We use a serializable impl. here as a workaround for @QuarkusTest instances, whose parameters
// are deep-cloned by the Quarkus test extension.
return new ClientFactory(uri, apiVersion, responseFactoryClass);
return new ClientFactory(uri, mainConfigSource, apiVersion, responseFactoryClass);
}

private static class ClientFactory implements NessieClientFactory, Serializable {

private final URI resolvedUri;
private final NessieClientConfigSource mainConfigSource;
private final NessieApiVersion apiVersion;
private final Class<? extends HttpResponseFactory> responseFactoryClass;

private ClientFactory(
URI nessieUri,
NessieClientConfigSource mainConfigSource,
NessieApiVersion apiVersion,
Class<? extends HttpResponseFactory> responseFactoryClass) {
this.resolvedUri = nessieUri;
this.mainConfigSource = mainConfigSource;
this.apiVersion = apiVersion;
this.responseFactoryClass = responseFactoryClass;
}
Expand All @@ -158,17 +174,19 @@ public NessieApiVersion apiVersion() {
@jakarta.annotation.Nonnull
@Override
public NessieApiV1 make(NessieClientCustomizer customizer) {
HttpClientBuilder clientBuilder = HttpClientBuilder.builder().withUri(resolvedUri);
NessieClientBuilder clientBuilder =
createClientBuilderFromSystemSettings(mainConfigSource).withUri(resolvedUri);
if (responseFactoryClass != null) {
try {
clientBuilder =
clientBuilder.withResponseFactory(
responseFactoryClass.getDeclaredConstructor().newInstance());
clientBuilder
.asInstanceOf(NessieHttpClientBuilder.class)
.withResponseFactory(responseFactoryClass.getDeclaredConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
NessieClientBuilder<?> builder = customizer.configure(clientBuilder, apiVersion);
NessieClientBuilder builder = customizer.configure(clientBuilder, apiVersion);
return apiVersion.build(builder);
}
}
Expand Down
Loading

0 comments on commit 81b34b6

Please sign in to comment.