This is an automated email from the ASF dual-hosted git repository. jshao pushed a commit to branch branch-gvfs-fuse-dev in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit ffbcb41137ee9a6e27d6505ceff4b56f0dcb5be0 Author: FANNG <[email protected]> AuthorDate: Wed Dec 4 10:07:07 2024 +0800 [#5619] feat(api): supports credential api for Gravitino (#5690) ### What changes were proposed in this pull request? This is the first PR of credential vending for Gravitino server to add credential API , please refer to #5682 for the overall workflow. Examples to use the API: ```java Catalog catalog = metalake.loadCatalog(catalogName); Credential[] credentials = catalog.supportsCredentials().getCredentials(); Credential credential = catalog.supportsCredentials().getCredential(“s3-token”); ``` ```java Fileset fileset = catalog.asFilesetCatalog().loadFileset(filesetIdent); Credential[] credentials = fileset.supportsCredentials().getCredentials(); Credential credential = fileset.supportsCredentials().getCredential(“s3-token”); ``` ### Why are the changes needed? Fix: #5619 ### Does this PR introduce _any_ user-facing change? no ### How was this patch tested? using draft PR to do E2E test --- .../main/java/org/apache/gravitino/Catalog.java | 9 +++ .../gravitino/credential/SupportsCredentials.java | 77 ++++++++++++++++++++++ .../exceptions/NoSuchCredentialException.java | 38 +++++++++++ .../java/org/apache/gravitino/file/Fileset.java | 9 +++ 4 files changed, 133 insertions(+) diff --git a/api/src/main/java/org/apache/gravitino/Catalog.java b/api/src/main/java/org/apache/gravitino/Catalog.java index ba8cf28d2..ce3bcc95c 100644 --- a/api/src/main/java/org/apache/gravitino/Catalog.java +++ b/api/src/main/java/org/apache/gravitino/Catalog.java @@ -22,6 +22,7 @@ import java.util.Locale; import java.util.Map; import org.apache.gravitino.annotation.Evolving; import org.apache.gravitino.authorization.SupportsRoles; +import org.apache.gravitino.credential.SupportsCredentials; import org.apache.gravitino.file.FilesetCatalog; import org.apache.gravitino.messaging.TopicCatalog; import org.apache.gravitino.model.ModelCatalog; @@ -207,4 +208,12 @@ public interface Catalog extends Auditable { default SupportsRoles supportsRoles() throws UnsupportedOperationException { throw new UnsupportedOperationException("Catalog does not support role operations"); } + + /** + * @return the {@link SupportsCredentials} if the catalog supports credential operations. + * @throws UnsupportedOperationException if the catalog does not support credential operations. + */ + default SupportsCredentials supportsCredentials() throws UnsupportedOperationException { + throw new UnsupportedOperationException("Catalog does not support credential operations"); + } } diff --git a/api/src/main/java/org/apache/gravitino/credential/SupportsCredentials.java b/api/src/main/java/org/apache/gravitino/credential/SupportsCredentials.java new file mode 100644 index 000000000..678172c42 --- /dev/null +++ b/api/src/main/java/org/apache/gravitino/credential/SupportsCredentials.java @@ -0,0 +1,77 @@ +/* + * 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.gravitino.credential; + +import com.google.common.base.Preconditions; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.exceptions.NoSuchCredentialException; + +/** Interface to get credentials. */ +public interface SupportsCredentials { + + /** + * Retrieves an array of {@link Credential} objects. + * + * @return An array of {@link Credential} objects. In most cases the array only contains one + * credential. If the object like {@link org.apache.gravitino.file.Fileset} contains multiple + * locations for different storages like HDFS, S3, the array will contain multiple + * credentials. The array could be empty if you request a credential for a catalog but the + * credential provider couldn't generate the credential for the catalog, like S3 token + * credential provider only generate credential for the specific object like {@link + * org.apache.gravitino.file.Fileset}, {@link org.apache.gravitino.rel.Table}. There will be + * at most one credential for one credential type. + */ + Credential[] getCredentials() throws NoSuchCredentialException; + + /** + * Retrieves an {@link Credential} object based on the specified credential type. + * + * @param credentialType The type of the credential like s3-token, s3-secret-key which defined in + * the specific credentials. + * @return An {@link Credential} object with the specified credential type. + * @throws NoSuchCredentialException If the specific credential cannot be found. + */ + default Credential getCredential(String credentialType) throws NoSuchCredentialException { + Preconditions.checkArgument( + StringUtils.isNotBlank(credentialType), "Credential type should not be empty"); + Credential[] credentials = getCredentials(); + if (credentials.length == 0) { + throw new NoSuchCredentialException( + "No credential found for the credential type: %s", credentialType); + } + + List<Credential> filteredCredentials = + Arrays.stream(credentials) + .filter(credential -> credentialType.equals(credential.credentialType())) + .collect(Collectors.toList()); + if (filteredCredentials.isEmpty()) { + throw new NoSuchCredentialException( + "No credential found for the credential type: %s", credentialType); + } else if (credentials.length > 1) { + throw new IllegalStateException( + "Multiple credentials found for the credential type:" + credentialType); + } + + return filteredCredentials.get(0); + } +} diff --git a/api/src/main/java/org/apache/gravitino/exceptions/NoSuchCredentialException.java b/api/src/main/java/org/apache/gravitino/exceptions/NoSuchCredentialException.java new file mode 100644 index 000000000..9869d1e72 --- /dev/null +++ b/api/src/main/java/org/apache/gravitino/exceptions/NoSuchCredentialException.java @@ -0,0 +1,38 @@ +/* + * 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.gravitino.exceptions; + +import com.google.errorprone.annotations.FormatMethod; +import com.google.errorprone.annotations.FormatString; + +/** An exception thrown when the request credential type is not found. */ +public class NoSuchCredentialException extends NotFoundException { + + /** + * Constructs a new exception with the specified detail message. + * + * @param message the detail message. + * @param args the arguments to the message. + */ + @FormatMethod + public NoSuchCredentialException(@FormatString String message, Object... args) { + super(message, args); + } +} diff --git a/api/src/main/java/org/apache/gravitino/file/Fileset.java b/api/src/main/java/org/apache/gravitino/file/Fileset.java index 97afcc650..6ada5f8c4 100644 --- a/api/src/main/java/org/apache/gravitino/file/Fileset.java +++ b/api/src/main/java/org/apache/gravitino/file/Fileset.java @@ -25,6 +25,7 @@ import org.apache.gravitino.Auditable; import org.apache.gravitino.Namespace; import org.apache.gravitino.annotation.Evolving; import org.apache.gravitino.authorization.SupportsRoles; +import org.apache.gravitino.credential.SupportsCredentials; import org.apache.gravitino.tag.SupportsTags; /** @@ -123,4 +124,12 @@ public interface Fileset extends Auditable { default SupportsRoles supportsRoles() { throw new UnsupportedOperationException("Fileset does not support role operations."); } + + /** + * @return The {@link SupportsCredentials} if the fileset supports credential operations. + * @throws UnsupportedOperationException If the fileset does not support credential operations. + */ + default SupportsCredentials supportsCredentials() { + throw new UnsupportedOperationException("Fileset does not support credential operations."); + } }
