This is an automated email from the ASF dual-hosted git repository.
pvillard31 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-api.git
The following commit(s) were added to refs/heads/main by this push:
new da671be Implemented ability to migrate a Versioned flow's Assets and
config to a new Connector (#88)
da671be is described below
commit da671becc47478de2363df980a500d77df2fb5ff
Author: Mark Payne <[email protected]>
AuthorDate: Fri May 15 12:11:48 2026 -0400
Implemented ability to migrate a Versioned flow's Assets and config to a
new Connector (#88)
---
.../migration/ConnectorMigrationContext.java | 75 ++++++++++++++++++
.../connector/migration/MigratableConnector.java | 92 ++++++++++++++++++++++
2 files changed, 167 insertions(+)
diff --git
a/src/main/java/org/apache/nifi/components/connector/migration/ConnectorMigrationContext.java
b/src/main/java/org/apache/nifi/components/connector/migration/ConnectorMigrationContext.java
new file mode 100644
index 0000000..e3ae61e
--- /dev/null
+++
b/src/main/java/org/apache/nifi/components/connector/migration/ConnectorMigrationContext.java
@@ -0,0 +1,75 @@
+/*
+ * 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.migration;
+
+import org.apache.nifi.components.connector.AssetReference;
+import org.apache.nifi.components.connector.components.FlowContext;
+import org.apache.nifi.flow.VersionedExternalFlow;
+
+/**
+ * Context provided to a Connector when evaluating or performing migration
from a Versioned Process Group export. The
+ * source flow exposed through this context is a read-only reference that the
Connector uses to update its own managed
+ * flow; the source flow itself is never installed onto the Connector.
+ */
+public interface ConnectorMigrationContext {
+
+ /**
+ * Returns the source flow whose configuration, parameters, and component
state the Connector should mirror into
+ * its own managed flow.
+ *
+ * @return the source flow
+ */
+ VersionedExternalFlow getSourceFlow();
+
+ /**
+ * Indicates whether the migration source is a local Versioned Process
Group on this NiFi instance.
+ *
+ * @return {@code true} when the source is local
+ */
+ boolean isLocalMigration();
+
+ /**
+ * Returns the active flow context for the Connector being migrated.
+ *
+ * @return the active flow context
+ */
+ FlowContext getActiveFlowContext();
+
+ /**
+ * Copies the referenced source asset into the Connector asset namespace.
+ *
+ * <p>
+ * When the source asset cannot be located in the source asset manager
(for example because it was deleted from
+ * the local source after the migration request started), the framework
logs a warning and returns an
+ * {@link AssetReference} whose {@link
AssetReference#getAssetIdentifiers()} returns an empty set, so the
+ * Connector can continue the migration without the missing asset. An
empty asset reference is a normal,
+ * expected return value and is the explicit signal that the asset was not
migrated; callers should detect this
+ * by checking whether {@code getAssetIdentifiers()} is empty and decide
how to handle that for the affected
+ * parameter (typically by leaving the parameter without an asset
reference for the user to re-attach after
+ * migration completes).
+ * </p>
+ *
+ * @param sourceAssetId the identifier of the source asset
+ * @return an asset reference for the newly copied asset, or an asset
reference with no identifiers when the
+ * source asset could not be located
+ * @throws IllegalArgumentException when {@code sourceAssetId} is null or
blank
+ * @throws IllegalStateException when invoked on an uploaded-payload
migration context; assets are only
+ * available when the migration source is a
local Versioned Process Group
+ */
+ AssetReference copyAssetFromSource(String sourceAssetId);
+}
diff --git
a/src/main/java/org/apache/nifi/components/connector/migration/MigratableConnector.java
b/src/main/java/org/apache/nifi/components/connector/migration/MigratableConnector.java
new file mode 100644
index 0000000..4dcdbd8
--- /dev/null
+++
b/src/main/java/org/apache/nifi/components/connector/migration/MigratableConnector.java
@@ -0,0 +1,92 @@
+/*
+ * 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.migration;
+
+import org.apache.nifi.components.connector.Connector;
+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.VersionedExternalFlow;
+
+/**
+ * <p>
+ * An optional capability interface that may be implemented by a {@link
Connector} to indicate that it supports
+ * being populated from an existing source flow (for example, a Versioned
Process Group already running on this
+ * NiFi instance, or an uploaded flow definition). The framework discovers
this capability by checking whether a
+ * Connector is an instance of {@code MigratableConnector}; Connectors that do
not implement this interface are
+ * never offered as migration targets.
+ * </p>
+ *
+ * <b>Implementation Note:</b> This API is currently experimental, as it is
under very active development. As such,
+ * it is subject to change without notice between releases.
+ */
+public interface MigratableConnector {
+
+ /**
+ * Indicates whether this Connector can be migrated from the source flow
described by the given context.
+ *
+ * <p>
+ * Implementations should inspect the source flow structure and metadata
using
+ * {@link ConnectorMigrationContext#getSourceFlow()} and return quickly
without mutating the Connector or the
+ * source flow. This method must not call {@link
ConnectorMigrationContext#copyAssetFromSource(String)}.
+ * </p>
+ *
+ * @param context the migration context describing the source flow and
target Connector
+ * @return {@code true} when this Connector can be migrated from the
provided source flow
+ */
+ boolean isMigrationSupported(ConnectorMigrationContext context);
+
+ /**
+ * Migrates this Connector by updating its own managed flow to mirror the
configuration, parameters, and component
+ * state captured in the provided source flow. The source flow is a
reference: it is read, not modified, and is not
+ * installed onto the Connector. The Connector remains the owner of its
flow and is responsible for translating the
+ * source into its own representation.
+ *
+ * <p>
+ * The framework guarantees the following preconditions when this method
is invoked:
+ * </p>
+ * <ul>
+ * <li>The Connector is stopped.</li>
+ * <li>The Connector has not had any configuration changes applied by
the user and has not been started.</li>
+ * </ul>
+ *
+ * <p>
+ * Because of these preconditions, the implementation updates the active
{@link FlowContext} directly rather than
+ * making use of {@code prepareForUpdate} and {@code applyUpdate}. Those
two lifecycle methods exist to safely
+ * transition a running Connector from one active configuration to
another; for migration, the Connector is
+ * already required to be in the target-safe state, so the
working-to-active swap is unnecessary.
+ * </p>
+ *
+ * <p>
+ * Implementations are responsible for transforming the source flow,
updating the active {@link FlowContext}, and
+ * applying any parameter or step configuration changes needed by the
Connector. Sensitive parameter values are not
+ * present in the source flow and must be left for the user to configure
after the migration completes.
+ * </p>
+ *
+ * <p>
+ * Connectors that extend {@code AbstractConnector} can typically retain
their {@link ConnectorInitializationContext}
+ * from {@code initialize(ConnectorInitializationContext)} and call
+ * {@link ConnectorInitializationContext#updateFlow(FlowContext,
VersionedExternalFlow)} using
+ * {@link ConnectorMigrationContext#getActiveFlowContext()}.
+ * </p>
+ *
+ * @param context the migration context describing the source flow and
target Connector
+ * @throws FlowUpdateException when the migration cannot be completed
successfully
+ */
+ void migrate(ConnectorMigrationContext context) throws FlowUpdateException;
+}