Skip to content
Merged
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,60 @@
/*
* 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.polaris.core.rest;

import com.google.common.collect.ImmutableSet;
import java.util.Set;
import org.apache.iceberg.rest.Endpoint;
import org.apache.polaris.core.config.FeatureConfiguration;
import org.apache.polaris.core.context.CallContext;

public class PolarisEndpoints {
public static final Endpoint V1_LIST_GENERIC_TABLES =
Endpoint.create("GET", PolarisResourcePaths.V1_GENERIC_TABLES);
public static final Endpoint V1_LOAD_GENERIC_TABLE =
Endpoint.create("GET", PolarisResourcePaths.V1_GENERIC_TABLE);
public static final Endpoint V1_CREATE_GENERIC_TABLE =
Endpoint.create("POST", PolarisResourcePaths.V1_GENERIC_TABLES);
public static final Endpoint V1_DELETE_GENERIC_TABLE =
Endpoint.create("DELETE", PolarisResourcePaths.V1_GENERIC_TABLE);

public static final Set<Endpoint> GENERIC_TABLE_ENDPOINTS =
ImmutableSet.<Endpoint>builder()
.add(V1_LIST_GENERIC_TABLES)
.add(V1_CREATE_GENERIC_TABLE)
.add(V1_DELETE_GENERIC_TABLE)
.add(V1_LOAD_GENERIC_TABLE)
.build();

/**
* Get the generic table endpoints. Returns GENERIC_TABLE_ENDPOINTS if ENABLE_GENERIC_TABLES is
* set to true, otherwise, returns an empty set.
*/
public static Set<Endpoint> getSupportedGenericTableEndpoints(CallContext callContext) {
// add the generic table endpoints as supported endpoints if generic table feature is enabled.
boolean genericTableEnabled =
callContext
.getPolarisCallContext()
.getConfigurationStore()
.getConfiguration(
callContext.getPolarisCallContext(), FeatureConfiguration.ENABLE_GENERIC_TABLES);

return genericTableEnabled ? GENERIC_TABLE_ENDPOINTS : ImmutableSet.of();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.polaris.core.rest;

import com.google.common.base.Joiner;
import java.util.Map;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.catalog.TableIdentifier;
import org.apache.iceberg.rest.RESTUtil;

public class PolarisResourcePaths {
private static final Joiner SLASH = Joiner.on("/").skipNulls();
public static final String PREFIX = "prefix";

// Generic Table endpoints
public static final String V1_GENERIC_TABLES =
"polaris/v1/{prefix}/namespaces/{namespace}/generic-tables";
public static final String V1_GENERIC_TABLE =
"polaris/v1/{prefix}/namespaces/{namespace}/generic-tables/{generic-table}";

private final String prefix;

public PolarisResourcePaths(String prefix) {
this.prefix = prefix;
}

public static PolarisResourcePaths forCatalogProperties(Map<String, String> properties) {
return new PolarisResourcePaths(properties.get(PREFIX));
}

public String genericTables(Namespace ns) {
return SLASH.join(
"polaris", "v1", prefix, "namespaces", RESTUtil.encodeNamespace(ns), "generic-tables");
}

public String genericTable(TableIdentifier ident) {
return SLASH.join(
"polaris",
"v1",
prefix,
"namespaces",
RESTUtil.encodeNamespace(ident.namespace()),
"generic-tables",
RESTUtil.encodeString(ident.name()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.polaris.core.rest;

import java.util.HashMap;
import java.util.Map;
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.catalog.TableIdentifier;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class PolarisResourcePathsTest {
private static final String testPrefix = "polaris-test";

private PolarisResourcePaths paths;

@BeforeEach
public void setUp() {
Map<String, String> properties = new HashMap<>();
properties.put(PolarisResourcePaths.PREFIX, testPrefix);
paths = PolarisResourcePaths.forCatalogProperties(properties);
}

@Test
public void testGenericTablesPath() {
Namespace ns = Namespace.of("ns1", "ns2");
String genericTablesPath = paths.genericTables(ns);
String expectedPath =
String.format("polaris/v1/%s/namespaces/%s/generic-tables", testPrefix, "ns1%1Fns2");
Assertions.assertThat(genericTablesPath).isEqualTo(expectedPath);
}

@Test
public void testGenericTablePath() {
Namespace ns = Namespace.of("ns1");
TableIdentifier ident = TableIdentifier.of(ns, "test-table");
String genericTablePath = paths.genericTable(ident);
String expectedPath =
String.format(
"polaris/v1/%s/namespaces/%s/generic-tables/%s", testPrefix, "ns1", "test-table");
Assertions.assertThat(genericTablePath).isEqualTo(expectedPath);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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.polaris.service.quarkus.catalog;

import static jakarta.ws.rs.core.Response.Status.CREATED;
import static org.assertj.core.api.Assertions.assertThat;

import io.quarkus.test.junit.QuarkusTest;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.iceberg.rest.responses.ConfigResponse;
import org.apache.polaris.core.admin.model.*;
import org.apache.polaris.core.rest.PolarisEndpoints;
import org.apache.polaris.service.TestServices;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

@QuarkusTest
public class GetConfigTest {
@ParameterizedTest
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@flyrain i removed the uncessary profile class definition here, which seems start causing some test flakyness.

@ValueSource(booleans = {true, false})
public void testGetConfig(boolean enableGenericTable) {
TestServices services =
TestServices.builder().config(Map.of("ENABLE_GENERIC_TABLES", enableGenericTable)).build();

FileStorageConfigInfo fileStorage =
FileStorageConfigInfo.builder(StorageConfigInfo.StorageTypeEnum.FILE)
.setAllowedLocations(List.of("file://"))
.build();
String catalogName = "test-catalog-" + UUID.randomUUID();
Catalog catalog =
PolarisCatalog.builder()
.setType(Catalog.TypeEnum.INTERNAL)
.setName(catalogName)
.setProperties(new CatalogProperties("file:///tmp/path/to/data"))
.setStorageConfigInfo(fileStorage)
.build();

Response response =
services
.catalogsApi()
.createCatalog(
new CreateCatalogRequest(catalog),
services.realmContext(),
services.securityContext());
assertThat(response.getStatus()).isEqualTo(CREATED.getStatusCode());

response =
services
.restConfigurationApi()
.getConfig(catalogName, services.realmContext(), services.securityContext());
ConfigResponse configResponse = response.readEntity(ConfigResponse.class);
assertThat(configResponse.overrides()).contains(Map.entry("prefix", catalogName));
if (enableGenericTable) {
assertThat(configResponse.endpoints()).contains(PolarisEndpoints.V1_CREATE_GENERIC_TABLE);
assertThat(configResponse.endpoints()).contains(PolarisEndpoints.V1_DELETE_GENERIC_TABLE);
assertThat(configResponse.endpoints()).contains(PolarisEndpoints.V1_LIST_GENERIC_TABLES);
assertThat(configResponse.endpoints()).contains(PolarisEndpoints.V1_LOAD_GENERIC_TABLE);
} else {
assertThat(configResponse.endpoints())
.doesNotContain(PolarisEndpoints.V1_CREATE_GENERIC_TABLE);
assertThat(configResponse.endpoints())
.doesNotContain(PolarisEndpoints.V1_DELETE_GENERIC_TABLE);
assertThat(configResponse.endpoints())
.doesNotContain(PolarisEndpoints.V1_LIST_GENERIC_TABLES);
assertThat(configResponse.endpoints()).doesNotContain(PolarisEndpoints.V1_LOAD_GENERIC_TABLE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
import org.apache.polaris.core.persistence.resolver.Resolver;
import org.apache.polaris.core.persistence.resolver.ResolverStatus;
import org.apache.polaris.core.rest.PolarisEndpoints;
import org.apache.polaris.service.catalog.AccessDelegationMode;
import org.apache.polaris.service.catalog.CatalogPrefixParser;
import org.apache.polaris.service.catalog.api.IcebergRestCatalogApiService;
Expand Down Expand Up @@ -711,6 +712,7 @@ public Response getConfig(
.addAll(DEFAULT_ENDPOINTS)
.addAll(VIEW_ENDPOINTS)
.addAll(COMMIT_ENDPOINT)
.addAll(PolarisEndpoints.getSupportedGenericTableEndpoints(callContext))
.build())
.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
import org.apache.polaris.service.admin.api.PolarisCatalogsApi;
import org.apache.polaris.service.catalog.DefaultCatalogPrefixParser;
import org.apache.polaris.service.catalog.api.IcebergRestCatalogApi;
import org.apache.polaris.service.catalog.api.IcebergRestCatalogApiService;
import org.apache.polaris.service.catalog.api.IcebergRestConfigurationApi;
import org.apache.polaris.service.catalog.iceberg.IcebergCatalogAdapter;
import org.apache.polaris.service.catalog.io.FileIOFactory;
import org.apache.polaris.service.catalog.io.MeasuredFileIOFactory;
Expand All @@ -64,6 +64,7 @@
public record TestServices(
PolarisCatalogsApi catalogsApi,
IcebergRestCatalogApi restApi,
IcebergRestConfigurationApi restConfigurationApi,
PolarisConfigurationStore configurationStore,
PolarisDiagnostics polarisDiagnostics,
RealmEntityManagerFactory entityManagerFactory,
Expand Down Expand Up @@ -170,7 +171,7 @@ public Map<String, Object> contextVariables() {
new PolarisCallContextCatalogFactory(
realmEntityManagerFactory, metaStoreManagerFactory, taskExecutor, fileIOFactory);

IcebergRestCatalogApiService service =
IcebergCatalogAdapter service =
new IcebergCatalogAdapter(
realmContext,
callContext,
Expand All @@ -181,6 +182,7 @@ public Map<String, Object> contextVariables() {
new DefaultCatalogPrefixParser());

IcebergRestCatalogApi restApi = new IcebergRestCatalogApi(service);
IcebergRestConfigurationApi restConfigurationApi = new IcebergRestConfigurationApi(service);

CreatePrincipalResult createdPrincipal =
metaStoreManager.createPrincipal(
Expand Down Expand Up @@ -225,6 +227,7 @@ public String getAuthenticationScheme() {
return new TestServices(
catalogsApi,
restApi,
restConfigurationApi,
configurationStore,
polarisDiagnostics,
realmEntityManagerFactory,
Expand Down