This is an automated email from the ASF dual-hosted git repository. lhotari pushed a commit to branch branch-4.2 in repository https://gitbox.apache.org/repos/asf/pulsar.git
commit e9ba10bd3849af30ab433a33f0a4835a04614cdb Author: sbourkeostk <[email protected]> AuthorDate: Thu May 21 10:25:36 2026 +0100 [fix][fn] Fix functions update issue where artifact is provided as a http url (#25840) Co-authored-by: Stephen Bourke <[email protected]> Co-authored-by: Lari Hotari <[email protected]> Co-authored-by: Zixuan Liu <[email protected]> (cherry picked from commit 235a7a8a4ca3cb6914f965ae2407030dbd1fa128) --- .../functions/worker/rest/api/ComponentImpl.java | 4 +-- .../api/v3/AbstractFunctionApiResourceTest.java | 39 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java index 4058ebb667c..f3bebd78de6 100644 --- a/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java +++ b/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java @@ -1776,7 +1776,7 @@ public abstract class ComponentImpl implements Component<PulsarWorkerService> { if (isNotBlank(functionPkgUrl)) { componentPackageFile = getPackageFile(componentType, functionPkgUrl); } else if (existingPackagePath.startsWith(Utils.FILE) || existingPackagePath.startsWith(Utils.HTTP)) { - if (!worker().getPackageUrlValidator().isValidPackageUrl(componentType, functionPkgUrl)) { + if (!worker().getPackageUrlValidator().isValidPackageUrl(componentType, existingPackagePath)) { throw new IllegalArgumentException("Function Package url is not valid." + "supported url (http/https/file)"); } @@ -1785,7 +1785,7 @@ public abstract class ComponentImpl implements Component<PulsarWorkerService> { } catch (Exception e) { throw new IllegalArgumentException(String.format("Encountered error \"%s\" " + "when getting %s package from %s", e.getMessage(), - ComponentTypeUtils.toString(componentType), functionPkgUrl)); + ComponentTypeUtils.toString(componentType), existingPackagePath)); } } else if (Utils.hasPackageTypePrefix(existingPackagePath)) { componentPackageFile = getPackageFile(componentType, existingPackagePath); diff --git a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/AbstractFunctionApiResourceTest.java b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/AbstractFunctionApiResourceTest.java index d7c5b877f63..16cf98b9847 100644 --- a/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/AbstractFunctionApiResourceTest.java +++ b/pulsar-functions/worker/src/test/java/org/apache/pulsar/functions/worker/rest/api/v3/AbstractFunctionApiResourceTest.java @@ -1028,6 +1028,45 @@ public abstract class AbstractFunctionApiResourceTest extends AbstractFunctionsR } + @Test + public void testUpdateFunctionWithExistingFileUrl() throws IOException { + + String fileLocation = FutureUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + String filePackageUrl = "file://" + fileLocation; + + FunctionConfig functionConfig = new FunctionConfig(); + functionConfig.setOutput(OUTPUT_TOPIC); + functionConfig.setOutputSerdeClassName(OUTPUT_SERDE_CLASS_NAME); + functionConfig.setTenant(TENANT); + functionConfig.setNamespace(NAMESPACE); + functionConfig.setName(FUNCTION); + functionConfig.setClassName(CLASS_NAME); + // increment parallelism to avoid 'Update contains no change' exception + functionConfig.setParallelism(PARALLELISM + 1); + functionConfig.setRuntime(FunctionConfig.Runtime.JAVA); + functionConfig.setCustomSerdeInputs(TOPICS_TO_SER_DE_CLASS_NAME); + + FunctionMetaData existingMetaData = FunctionMetaData.newBuilder() + .setFunctionDetails(createDefaultFunctionDetails()) + .setPackageLocation(org.apache.pulsar.functions.proto.Function.PackageLocationMetaData.newBuilder() + .setPackagePath(filePackageUrl) + .build()) + .build(); + + when(mockedManager.containsFunction(eq(TENANT), eq(NAMESPACE), eq(FUNCTION))).thenReturn(true); + when(mockedManager.getFunctionMetaData(any(), any(), any())).thenReturn(existingMetaData); + + updateFunction( + TENANT, + NAMESPACE, + FUNCTION, + null, + null, + null, + functionConfig, + null, null); + } + @Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "function failed to register") public void testUpdateFunctionFailure() throws Exception { try {
