This is an automated email from the ASF dual-hosted git repository.
bbende pushed a commit to branch NIFI-15258
in repository https://gitbox.apache.org/repos/asf/nifi-api.git
The following commit(s) were added to refs/heads/NIFI-15258 by this push:
new 5749b54 NIFI-15467: Allow Connectors to specify bundle compatability
when upd… (#54)
5749b54 is described below
commit 5749b548d4cb36dd4d4a0e830ff593d779e7b6f3
Author: Mark Payne <[email protected]>
AuthorDate: Tue Jan 27 09:03:52 2026 -0500
NIFI-15467: Allow Connectors to specify bundle compatability when upd… (#54)
* NIFI-15467: Allow Connectors to specify bundle compatability when
updating flow
* NIFI-15467: Have ComponentBundleLookup return Optional<Bundle> from
getLatestBundle instead of a nullable Bundle
---
.../components/connector/BundleCompatibility.java | 47 ++++++++++++++++++++++
.../connector/ComponentBundleLookup.java | 36 +++++++++++++++++
.../connector/ConnectorInitializationContext.java | 28 ++++++++++++-
...ocumentationConnectorInitializationContext.java | 18 ++++++++-
4 files changed, 125 insertions(+), 4 deletions(-)
diff --git
a/src/main/java/org/apache/nifi/components/connector/BundleCompatibility.java
b/src/main/java/org/apache/nifi/components/connector/BundleCompatibility.java
new file mode 100644
index 0000000..b17eb38
--- /dev/null
+++
b/src/main/java/org/apache/nifi/components/connector/BundleCompatibility.java
@@ -0,0 +1,47 @@
+/*
+ * 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.nifi.components.connector;
+
+/**
+ * Specifies how bundle resolution should be handled when updating a flow with
components
+ * whose specified bundles may not be available in the NiFi instance.
+ */
+public enum BundleCompatibility {
+
+ /**
+ * Requires the exact bundle specified in the flow. If the bundle is not
available,
+ * a ghosted component will be created. This is the default behavior.
+ */
+ REQUIRE_EXACT_BUNDLE,
+
+ /**
+ * If the specified bundle is not available, checks what bundles are
available for
+ * the given component type. If exactly one bundle is available, resolves
to that bundle.
+ * If no bundles or multiple bundles are available, uses the specified
bundle and
+ * creates a ghosted component.
+ */
+ RESOLVE_BUNDLE,
+
+ /**
+ * If the specified bundle is not available, checks what bundles are
available for
+ * the given component type. If no bundles are available, uses the
specified bundle
+ * and creates a ghosted component. Otherwise, uses the newest available
bundle
+ * based on version comparison.
+ */
+ RESOLVE_NEWEST_BUNDLE
+}
diff --git
a/src/main/java/org/apache/nifi/components/connector/ComponentBundleLookup.java
b/src/main/java/org/apache/nifi/components/connector/ComponentBundleLookup.java
index 7abe996..84cba63 100644
---
a/src/main/java/org/apache/nifi/components/connector/ComponentBundleLookup.java
+++
b/src/main/java/org/apache/nifi/components/connector/ComponentBundleLookup.java
@@ -20,6 +20,7 @@ package org.apache.nifi.components.connector;
import org.apache.nifi.flow.Bundle;
import java.util.List;
+import java.util.Optional;
public interface ComponentBundleLookup {
@@ -30,4 +31,39 @@ public interface ComponentBundleLookup {
*/
List<Bundle> getAvailableBundles(String componentType);
+ /**
+ * Determines the latest bundle available for the given component type
based on version comparison.
+ *
+ * <p>Version comparison follows these rules:</p>
+ * <ol>
+ * <li>Versions are split by dots (e.g., "2.1.0" becomes ["2", "1",
"0"]).
+ * This also supports calendar-date formats (e.g.,
"2026.01.01").</li>
+ * <li>Each part is compared numerically when possible; numeric parts
are considered
+ * newer than non-numeric parts (e.g., "2.0.0" > "2.0.next")</li>
+ * <li>When base versions are equal, qualifiers are compared with the
following precedence
+ * (highest to lowest):
+ * <ul>
+ * <li>Release (no qualifier)</li>
+ * <li>RC (Release Candidate) - e.g., "-RC1", "-RC2"</li>
+ * <li>M (Milestone) - e.g., "-M1", "-M2"</li>
+ * <li>Other/unknown qualifiers</li>
+ * <li>SNAPSHOT</li>
+ * </ul>
+ * </li>
+ * <li>Within the same qualifier type, numeric suffixes are compared
+ * (e.g., "2.0.0-RC2" > "2.0.0-RC1", "2.0.0-M4" >
"2.0.0-M1")</li>
+ * </ol>
+ *
+ * <p>Examples of version ordering (highest to lowest):</p>
+ * <ul>
+ * <li>3.0.0 > 2.1.0 > 2.0.0 > 2.0.0-RC2 > 2.0.0-RC1 >
2.0.0-M4 > 2.0.0-M1 > 2.0.0-SNAPSHOT</li>
+ * <li>2.1.0-SNAPSHOT > 2.0.0 (higher base version wins)</li>
+ * <li>2026.01.01 > 2025.12.31 (calendar-date format)</li>
+ * </ul>
+ *
+ * @param componentType the component type
+ * @return an Optional containing the latest available bundle, or empty if
no bundles are available
+ */
+ Optional<Bundle> getLatestBundle(String componentType);
+
}
diff --git
a/src/main/java/org/apache/nifi/components/connector/ConnectorInitializationContext.java
b/src/main/java/org/apache/nifi/components/connector/ConnectorInitializationContext.java
index 88880f9..fa422b4 100644
---
a/src/main/java/org/apache/nifi/components/connector/ConnectorInitializationContext.java
+++
b/src/main/java/org/apache/nifi/components/connector/ConnectorInitializationContext.java
@@ -70,7 +70,6 @@ public interface ConnectorInitializationContext {
* <li>Restarting all components</li>
* </ul>
*
- *
* <p>
* Depending on the changes required in order to update the flow to
the provided VersionedProcessGroup, this
* could also result in stopping source processors and waiting for
queues to drain, etc.
@@ -82,9 +81,34 @@ public interface ConnectorInitializationContext {
* be started.
* </p>
*
+ * <p>
+ * This method uses the Bundle Compatability strategy of {@link
BundleCompatibility#RESOLVE_BUNDLE}.
+ * </p>
+ *
+ * @param flowContext the context of the flow to be updated
+ * @param versionedExternalFlow the new representation of the flow
+ */
+ default void updateFlow(FlowContext flowContext, VersionedExternalFlow
versionedExternalFlow) throws FlowUpdateException {
+ updateFlow(flowContext, versionedExternalFlow,
BundleCompatibility.RESOLVE_BUNDLE);
+ }
+
+ /**
+ * <p>
+ * Updates the Connector's flow to the given VersionedExternalFlow with
the specified bundle compatibility strategy.
+ * This method behaves like {@link #updateFlow(FlowContext,
VersionedExternalFlow)} but allows control over how
+ * component bundles are resolved when the specified bundle is not
available.
+ * </p>
+ *
+ * <p>
+ * Note that if Bundle Compatability is not set to {@link
BundleCompatibility#REQUIRE_EXACT_BUNDLE}, this method may update the provided
+ * VersionedExternalFlow to represent the actual bundles used during
the update.
+ * </p>
+ *
* @param flowContext the context of the flow to be updated
* @param versionedExternalFlow the new representation of the flow
+ * @param bundleCompatability the strategy to use when resolving component
bundles
+ * @throws FlowUpdateException if the flow update fails
*/
- void updateFlow(FlowContext flowContext, VersionedExternalFlow
versionedExternalFlow) throws FlowUpdateException;
+ void updateFlow(FlowContext flowContext, VersionedExternalFlow
versionedExternalFlow, BundleCompatibility bundleCompatability) throws
FlowUpdateException;
}
diff --git
a/src/main/java/org/apache/nifi/documentation/init/DocumentationConnectorInitializationContext.java
b/src/main/java/org/apache/nifi/documentation/init/DocumentationConnectorInitializationContext.java
index 75bc7e0..1eeb802 100644
---
a/src/main/java/org/apache/nifi/documentation/init/DocumentationConnectorInitializationContext.java
+++
b/src/main/java/org/apache/nifi/documentation/init/DocumentationConnectorInitializationContext.java
@@ -16,14 +16,17 @@
*/
package org.apache.nifi.documentation.init;
+import org.apache.nifi.components.connector.BundleCompatibility;
import org.apache.nifi.components.connector.ComponentBundleLookup;
import org.apache.nifi.components.connector.ConnectorInitializationContext;
import org.apache.nifi.components.connector.FlowUpdateException;
import org.apache.nifi.components.connector.components.FlowContext;
+import org.apache.nifi.flow.Bundle;
import org.apache.nifi.flow.VersionedExternalFlow;
import org.apache.nifi.logging.ComponentLog;
import java.util.List;
+import java.util.Optional;
import java.util.UUID;
/**
@@ -51,11 +54,22 @@ public class DocumentationConnectorInitializationContext
implements ConnectorIni
@Override
public ComponentBundleLookup getComponentBundleLookup() {
- return componentType -> List.of();
+ return new ComponentBundleLookup() {
+ @Override
+ public List<Bundle> getAvailableBundles(final String
componentType) {
+ return List.of();
+ }
+
+ @Override
+ public Optional<Bundle> getLatestBundle(final String
componentType) {
+ return Optional.empty();
+ }
+ };
}
@Override
- public void updateFlow(final FlowContext flowContext, final
VersionedExternalFlow versionedExternalFlow) throws FlowUpdateException {
+ public void updateFlow(final FlowContext flowContext, final
VersionedExternalFlow versionedExternalFlow,
+ final BundleCompatibility bundleCompatability)
throws FlowUpdateException {
// No-op for documentation purposes - we don't actually update any
flows
}
}