This is an automated email from the ASF dual-hosted git repository.
markap14 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 6e674d8c77 NIFI-15267 Perform validation when enabling Controller
Services (#10572)
6e674d8c77 is described below
commit 6e674d8c77b402a4438fb41f55e98f345dd0bdbe
Author: David Handermann <[email protected]>
AuthorDate: Tue Dec 2 11:11:00 2025 -0600
NIFI-15267 Perform validation when enabling Controller Services (#10572)
- Updated StandardControllerServiceNode enable method to perform validation
before checking status
- Added system test with 12 Controller Services that require property
renaming
- Added incremental delay for validation and enabling
---
.../service/StandardControllerServiceNode.java | 85 ++-
.../system/MigratePropertiesCountService.java | 69 ++
.../org.apache.nifi.controller.ControllerService | 1 +
.../SpawnedStandaloneNiFiInstanceFactory.java | 9 +-
.../ControllerServiceEnablingFailureIT.java | 96 +++
.../migration/MigratePropertiesCountServiceIT.java | 105 ++++
.../system/migration/PropertyMigrationIT.java | 10 +
.../controller-service-enabling-failure/flow.json | 95 +++
.../resources/flows/migrate-properties/flow.json | 695 +++++++++++++++++++++
9 files changed, 1129 insertions(+), 36 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
index 1ebd2237c6..ac0e91fada 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java
@@ -73,7 +73,9 @@ import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
+import java.time.Duration;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -99,6 +101,8 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
private static final Logger LOG =
LoggerFactory.getLogger(StandardControllerServiceNode.class);
+ private static final long INCREMENTAL_VALIDATION_DELAY_MS = 1000;
+ private static final Duration MAXIMUM_DELAY = Duration.ofMinutes(10);
private final AtomicReference<ControllerServiceDetails>
controllerServiceHolder = new AtomicReference<>(null);
private final ControllerServiceProvider serviceProvider;
@@ -612,47 +616,51 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
this.active.set(true);
}
+ final AtomicLong enablingDelay = new AtomicLong(0);
+ final AtomicLong validationDelay = new AtomicLong(0);
final ControllerServiceProvider controllerServiceProvider =
this.serviceProvider;
- final StandardControllerServiceNode service = this;
- AtomicLong enablingAttemptCount = new AtomicLong(0);
+ final StandardControllerServiceNode serviceNode = this;
scheduler.execute(new Runnable() {
@Override
public void run() {
- final ConfigurationContext configContext = new
StandardConfigurationContext(StandardControllerServiceNode.this,
controllerServiceProvider, null);
+ final ConfigurationContext configContext = new
StandardConfigurationContext(serviceNode, controllerServiceProvider, null);
if (!isActive()) {
- LOG.warn("Enabling {} stopped: no active status",
StandardControllerServiceNode.this);
+ LOG.warn("Enabling {} stopped: no active status",
serviceNode);
stateTransition.disable();
future.complete(null);
return;
}
- final ValidationStatus validationStatus =
getValidationStatus();
- if (validationStatus != ValidationStatus.VALID) {
- final ValidationState validationState =
getValidationState();
- LOG.debug("Enabling {} failed: Validation Status [{}]
Errors {} Attempt [{}] Retrying...",
- StandardControllerServiceNode.this, validationStatus,
validationState.getValidationErrors(), enablingAttemptCount.get());
-
- enablingAttemptCount.incrementAndGet();
- if (enablingAttemptCount.get() == 120 ||
enablingAttemptCount.get() % 3600 == 0) {
- final ControllerService controllerService =
getControllerServiceImplementation();
- final ComponentLog componentLog = new
SimpleProcessLogger(getIdentifier(), controllerService,
- new
StandardLoggingContext(StandardControllerServiceNode.this));
- componentLog.error("Enabling {} failed: Validation
Status [{}] Errors {}",
- service, validationStatus,
validationState.getValidationErrors());
- }
+ // Perform Validation and evaluate status before continuing
+ performValidation();
+ final ValidationState validationState = getValidationState();
+ final ValidationStatus validationStatus =
validationState.getStatus();
+ if (validationStatus == ValidationStatus.VALID) {
+ LOG.debug("Enabling {} proceeding after performing
validation", serviceNode);
+ } else if (completeExceptionallyOnFailure) {
+ final Collection<ValidationResult> errors =
validationState.getValidationErrors();
+ final String message = "Enabling %s failed: Validation
Status [%s] Errors %s".formatted(serviceNode, validationStatus, errors);
+ future.completeExceptionally(new
IllegalStateException(message));
+ } else {
+ final long selectedValidationDelay =
getDelay(validationDelay, INCREMENTAL_VALIDATION_DELAY_MS);
- try {
- scheduler.schedule(this, 1, TimeUnit.SECONDS);
- } catch (final RejectedExecutionException
rejectedExecutionException) {
- LOG.error("Enabling {} failed: Validation Status [{}]
Errors {}", StandardControllerServiceNode.this, validationStatus,
validationState.getValidationErrors(),
- rejectedExecutionException);
+ // Log warning on repeated validation rescheduling
+ if (selectedValidationDelay > MAXIMUM_DELAY.toMillis()) {
+ final Collection<ValidationResult> errors =
validationState.getValidationErrors();
+ LOG.warn("Validation rescheduled in {} ms for {}
Errors {}", selectedValidationDelay, serviceNode, errors);
}
- if (completeExceptionallyOnFailure) {
- future.completeExceptionally(new
IllegalStateException("Cannot enable " + StandardControllerServiceNode.this + "
because it is not valid"));
+ try {
+ scheduler.schedule(this, selectedValidationDelay,
TimeUnit.MILLISECONDS);
+ LOG.debug("Validation rescheduled in {} ms for {}",
selectedValidationDelay, serviceNode);
+ } catch (final RejectedExecutionException e) {
+ LOG.error("Validation rescheduling rejected for {}",
serviceNode, e);
+ final Collection<ValidationResult> errors =
validationState.getValidationErrors();
+ final String message = "Enabling %s rejected:
Validation Status [%s] Errors %s".formatted(serviceNode, validationStatus,
errors);
+ future.completeExceptionally(new
IllegalStateException(message));
}
-
+ // Enable command rescheduled or rejected
return;
}
@@ -668,14 +676,14 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
}
if (!shouldEnable) {
- LOG.info("Disabling {} after enabled due to disable
action initiated", service);
+ LOG.info("Disabling {} after enabled due to disable
action initiated", serviceNode);
// Can only happen if user initiated DISABLE operation
before service finished enabling. It's state will be
// set to DISABLING (see disable() operation)
invokeDisable(configContext);
stateTransition.disable();
future.complete(null);
} else {
- LOG.info("Enabled {}", service);
+ LOG.info("Enabled {}", serviceNode);
}
} catch (final Exception e) {
if (completeExceptionallyOnFailure) {
@@ -683,13 +691,14 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
}
final Throwable cause = e instanceof
InvocationTargetException ? e.getCause() : e;
- final ComponentLog componentLog = new
SimpleProcessLogger(getIdentifier(), controllerService,
- new
StandardLoggingContext(StandardControllerServiceNode.this));
+ final ComponentLog componentLog = new
SimpleProcessLogger(getIdentifier(), controllerService, new
StandardLoggingContext(serviceNode));
componentLog.error("Failed to invoke @OnEnabled method",
cause);
invokeDisable(configContext);
if (isActive()) {
- scheduler.schedule(this, administrativeYieldMillis,
TimeUnit.MILLISECONDS);
+ // Increment enabling delay to avoid excessive retries
+ final long selectedEnablingDelay =
getDelay(enablingDelay, administrativeYieldMillis);
+ scheduler.schedule(this, selectedEnablingDelay,
TimeUnit.MILLISECONDS);
} else {
stateTransition.disable();
}
@@ -700,7 +709,6 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
return future;
}
-
/**
* Will atomically disable this service by invoking its @OnDisabled
operation.
* It uses CAS operation on {@link #stateTransition} to transition this
service
@@ -871,4 +879,17 @@ public class StandardControllerServiceNode extends
AbstractComponentNode impleme
protected void performFlowAnalysisOnThis() {
getValidationContextFactory().getFlowAnalyzer().ifPresent(flowAnalyzer
-> flowAnalyzer.analyzeControllerService(this));
}
+
+ private long getDelay(final AtomicLong trackedDelay, final long
incrementalDelay) {
+ final long selectedDelay;
+
+ final long currentDelay = trackedDelay.get();
+ if (currentDelay > MAXIMUM_DELAY.toMillis()) {
+ selectedDelay = currentDelay;
+ } else {
+ selectedDelay = trackedDelay.addAndGet(incrementalDelay);
+ }
+
+ return selectedDelay;
+ }
}
diff --git
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/java/org/apache/nifi/cs/tests/system/MigratePropertiesCountService.java
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/java/org/apache/nifi/cs/tests/system/MigratePropertiesCountService.java
new file mode 100644
index 0000000000..338705aa21
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/java/org/apache/nifi/cs/tests/system/MigratePropertiesCountService.java
@@ -0,0 +1,69 @@
+/*
+ * 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.cs.tests.system;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.migration.PropertyConfiguration;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MigratePropertiesCountService extends AbstractControllerService
implements CountService {
+ private static final String PREVIOUS_START_VALUE_PROPERTY_NAME =
"start-value";
+
+ private static final String PREVIOUS_COUNT_SERVICE_PROPERTY_NAME =
"count-service";
+
+ static final PropertyDescriptor START_VALUE = new
PropertyDescriptor.Builder()
+ .name("Start Value")
+ .description("Initial value for counting")
+ .required(true)
+ .addValidator(StandardValidators.LONG_VALIDATOR)
+ .defaultValue("0")
+ .build();
+
+ static final PropertyDescriptor COUNT_SERVICE = new
PropertyDescriptor.Builder()
+ .name("Count Service")
+ .description("Count Service for testing Controller Service
dependencies")
+ .required(false)
+ .identifiesControllerService(CountService.class)
+ .build();
+
+ private static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS =
List.of(
+ START_VALUE,
+ COUNT_SERVICE
+ );
+
+ private final AtomicLong counter = new AtomicLong();
+
+ @Override
+ protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ @Override
+ public void migrateProperties(final PropertyConfiguration
propertyConfiguration) {
+
propertyConfiguration.renameProperty(PREVIOUS_START_VALUE_PROPERTY_NAME,
START_VALUE.getName());
+
propertyConfiguration.renameProperty(PREVIOUS_COUNT_SERVICE_PROPERTY_NAME,
COUNT_SERVICE.getName());
+ }
+
+ @Override
+ public long count() {
+ return counter.getAndIncrement();
+ }
+}
diff --git
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
index 2983552663..a4da9272ec 100644
---
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
+++
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions-services/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
@@ -20,6 +20,7 @@ org.apache.nifi.cs.tests.system.LifecycleFailureService
org.apache.nifi.cs.tests.system.SensitiveDynamicPropertiesService
org.apache.nifi.cs.tests.system.StandardCountService
org.apache.nifi.cs.tests.system.StandardSleepService
+org.apache.nifi.cs.tests.system.MigratePropertiesCountService
org.apache.nifi.cs.tests.system.MigrationService
org.apache.nifi.cs.tests.system.MockCSVReader
org.apache.nifi.cs.tests.system.MockCSVWriter
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/SpawnedStandaloneNiFiInstanceFactory.java
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/SpawnedStandaloneNiFiInstanceFactory.java
index 9e40a1c00a..a8240c02ac 100644
---
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/SpawnedStandaloneNiFiInstanceFactory.java
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/SpawnedStandaloneNiFiInstanceFactory.java
@@ -270,9 +270,10 @@ public class SpawnedStandaloneNiFiInstanceFactory
implements NiFiInstanceFactory
}
try {
- Thread.sleep(1000L);
- } catch (InterruptedException ex) {
- logger.debug("NiFi Startup sleep interrupted", ex);
+ TimeUnit.SECONDS.sleep(1);
+ } catch (InterruptedException interrupted) {
+ logger.warn("NiFi Startup sleep interrupted",
interrupted);
+ break;
}
}
}
@@ -282,7 +283,7 @@ public class SpawnedStandaloneNiFiInstanceFactory
implements NiFiInstanceFactory
@Override
public void stop() {
if (process == null) {
- logger.info("NiFi Shutdown Ignored (runNiFi==null) [{}]",
instanceDirectory.getName());
+ logger.debug("NiFi Shutdown request ignored [{}]",
instanceDirectory.getName());
return;
}
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/controllerservice/ControllerServiceEnablingFailureIT.java
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/controllerservice/ControllerServiceEnablingFailureIT.java
new file mode 100644
index 0000000000..d5ad90883a
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/controllerservice/ControllerServiceEnablingFailureIT.java
@@ -0,0 +1,96 @@
+/*
+ * 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.tests.system.controllerservice;
+
+import org.apache.nifi.components.validation.ValidationStatus;
+import org.apache.nifi.stream.io.GZIPOutputStream;
+import org.apache.nifi.tests.system.InstanceConfiguration;
+import org.apache.nifi.tests.system.NiFiInstanceFactory;
+import org.apache.nifi.tests.system.NiFiSystemIT;
+import org.apache.nifi.tests.system.SpawnedStandaloneNiFiInstanceFactory;
+import org.apache.nifi.toolkit.client.NiFiClientException;
+import org.apache.nifi.web.api.dto.status.ControllerServiceStatusDTO;
+import org.apache.nifi.web.api.entity.ControllerServiceEntity;
+import org.apache.nifi.web.api.entity.ControllerServicesEntity;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ControllerServiceEnablingFailureIT extends NiFiSystemIT {
+ private static final String PARENT_GROUP_ID =
"c1a920de-019a-1000-6510-f3bca7dd9c69";
+
+ private static final String ENABLING_STATUS = "ENABLING";
+
+ /**
+ * Get Instance Factory using flow.json with property names that require
renaming
+ *
+ * @return NiFi Instance Factory
+ */
+ @Override
+ public NiFiInstanceFactory getInstanceFactory() {
+ final Path flowJsonInputPath =
Paths.get("src/test/resources/flows/controller-service-enabling-failure/flow.json");
+ final Path flowJsonOutputPath =
Paths.get("target/controller-service-enabling-failure-flow.json.gz").toAbsolutePath();
+ try (
+ InputStream inputStream =
Files.newInputStream(flowJsonInputPath);
+ OutputStream outputStream = new
GZIPOutputStream(Files.newOutputStream(flowJsonOutputPath))
+ ) {
+ inputStream.transferTo(outputStream);
+ } catch (final IOException e) {
+ throw new UncheckedIOException("Failed to compress Flow
Configuration [%s]".formatted(flowJsonInputPath), e);
+ }
+
+ return new SpawnedStandaloneNiFiInstanceFactory(
+ new InstanceConfiguration.Builder()
+
.bootstrapConfig("src/test/resources/conf/default/bootstrap.conf")
+ .instanceDirectory("target/standalone-instance")
+ .flowJson(flowJsonOutputPath.toFile())
+ .overrideNifiProperties(getNifiPropertiesOverrides())
+ .build()
+ );
+ }
+
+ @Override
+ protected boolean isAllowFactoryReuse() {
+ return false;
+ }
+
+ @Override
+ protected boolean isDestroyEnvironmentAfterEachTest() {
+ return true;
+ }
+
+ @Test
+ void testControllerServices() throws NiFiClientException, IOException {
+ final ControllerServicesEntity servicesEntity =
getNifiClient().getFlowClient().getControllerServices(PARENT_GROUP_ID);
+ assertEquals(1, servicesEntity.getControllerServices().size());
+
+ final ControllerServiceEntity controllerService =
servicesEntity.getControllerServices().iterator().next();
+ final ControllerServiceStatusDTO status =
controllerService.getStatus();
+ assertEquals(ValidationStatus.VALID.toString(),
status.getValidationStatus());
+
+ // ENABLING but not ENABLED based on LifecycleFailureService
implementation and framework enabling attempts
+ assertEquals(ENABLING_STATUS, status.getRunStatus());
+ }
+}
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/MigratePropertiesCountServiceIT.java
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/MigratePropertiesCountServiceIT.java
new file mode 100644
index 0000000000..3d73beef47
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/MigratePropertiesCountServiceIT.java
@@ -0,0 +1,105 @@
+/*
+ * 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.tests.system.migration;
+
+import org.apache.nifi.stream.io.GZIPOutputStream;
+import org.apache.nifi.tests.system.InstanceConfiguration;
+import org.apache.nifi.tests.system.NiFiInstanceFactory;
+import org.apache.nifi.tests.system.NiFiSystemIT;
+import org.apache.nifi.tests.system.SpawnedStandaloneNiFiInstanceFactory;
+import org.apache.nifi.toolkit.client.NiFiClientException;
+import org.apache.nifi.web.api.entity.ControllerServicesEntity;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.Timeout;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class MigratePropertiesCountServiceIT extends NiFiSystemIT {
+ private static final String PARENT_GROUP_ID =
"c1a920de-019a-1000-6510-f3bca7dd9c69";
+
+ private static final int CONFIGURED_CONTROLLER_SERVICES = 12;
+
+ /**
+ * Override setup method with Timeout annotation to verify Controller
Service validation timing
+ *
+ * @param testInfo Test Information
+ * @throws IOException Thrown on setup failures
+ */
+ @Timeout(value = 45, unit = TimeUnit.SECONDS)
+ @BeforeEach
+ @Override
+ public void setup(final TestInfo testInfo) throws IOException {
+ super.setup(testInfo);
+ }
+
+ /**
+ * Get Instance Factory using flow.json with property names that require
renaming
+ *
+ * @return NiFi Instance Factory
+ */
+ @Override
+ public NiFiInstanceFactory getInstanceFactory() {
+ final Path flowJsonInputPath =
Paths.get("src/test/resources/flows/migrate-properties/flow.json");
+ final Path flowJsonOutputPath =
Paths.get("target/migrate-properties-flow.json.gz").toAbsolutePath();
+ try (
+ InputStream inputStream =
Files.newInputStream(flowJsonInputPath);
+ OutputStream outputStream = new
GZIPOutputStream(Files.newOutputStream(flowJsonOutputPath))
+ ) {
+ inputStream.transferTo(outputStream);
+ } catch (final IOException e) {
+ throw new UncheckedIOException("Failed to compress Flow
Configuration [%s]".formatted(flowJsonInputPath), e);
+ }
+
+ return new SpawnedStandaloneNiFiInstanceFactory(
+ new InstanceConfiguration.Builder()
+
.bootstrapConfig("src/test/resources/conf/default/bootstrap.conf")
+ .instanceDirectory("target/standalone-instance")
+ .flowJson(flowJsonOutputPath.toFile())
+ .overrideNifiProperties(getNifiPropertiesOverrides())
+ .build()
+ );
+ }
+
+ @Override
+ protected boolean isAllowFactoryReuse() {
+ return false;
+ }
+
+ @Override
+ protected boolean isDestroyEnvironmentAfterEachTest() {
+ return true;
+ }
+
+ @Test
+ void testControllerServices() throws NiFiClientException, IOException {
+ getClientUtil().waitForControllerServicesEnabled(PARENT_GROUP_ID);
+
+ final ControllerServicesEntity servicesEntity =
getNifiClient().getFlowClient().getControllerServices(PARENT_GROUP_ID);
+ assertEquals(CONFIGURED_CONTROLLER_SERVICES,
servicesEntity.getControllerServices().size());
+ }
+}
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/PropertyMigrationIT.java
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/PropertyMigrationIT.java
index cde7059a52..4c74e0fbd1 100644
---
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/PropertyMigrationIT.java
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/migration/PropertyMigrationIT.java
@@ -52,6 +52,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class PropertyMigrationIT extends NiFiSystemIT {
private static final String SERVICE = "Service";
+ @Override
+ protected boolean isAllowFactoryReuse() {
+ return false;
+ }
+
+ @Override
+ protected boolean isDestroyEnvironmentAfterEachTest() {
+ return true;
+ }
+
@AfterEach
public void restoreNars() {
// Stop the NiFi instance, ensure that the
nifi-system-test-extensions-nar and nifi-alternate-config-extensions bundles
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/controller-service-enabling-failure/flow.json
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/controller-service-enabling-failure/flow.json
new file mode 100644
index 0000000000..32dd9ba211
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/controller-service-enabling-failure/flow.json
@@ -0,0 +1,95 @@
+{
+ "encodingVersion": {
+ "majorVersion": 2,
+ "minorVersion": 0
+ },
+ "maxTimerDrivenThreadCount": 10,
+ "registries": [],
+ "parameterContexts": [],
+ "parameterProviders": [],
+ "controllerServices": [],
+ "reportingTasks": [],
+ "flowAnalysisRules": [],
+ "rootGroup": {
+ "identifier": "10b0aac8-4c39-3a71-807a-60128ba1ef34",
+ "instanceIdentifier": "35e0b881-019a-1000-190e-b9f7878b3cad",
+ "name": "NiFi Flow",
+ "comments": "",
+ "position": {
+ "x": 0.0,
+ "y": 0.0
+ },
+ "processGroups": [
+ {
+ "identifier": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "instanceIdentifier": "c1a920de-019a-1000-6510-f3bca7dd9c69",
+ "name": "snapshot",
+ "comments": "",
+ "position": {
+ "x": -305.75,
+ "y": -385.75
+ },
+ "processGroups": [],
+ "remoteProcessGroups": [],
+ "processors": [],
+ "inputPorts": [],
+ "outputPorts": [],
+ "connections": [],
+ "labels": [],
+ "funnels": [],
+ "controllerServices": [
+ {
+ "identifier": "405590bc-42ab-352b-8b4c-10b1295437bb",
+ "instanceIdentifier": "c1ee80be-019a-1000-7fd0-7ecf915c9eb6",
+ "name": "LifecycleFailureService-0",
+ "comments": "",
+ "type": "org.apache.nifi.cs.tests.system.LifecycleFailureService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "Enable Failure Count": "1000"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ }
+ ],
+ "defaultFlowFileExpiration": "0 sec",
+ "defaultBackPressureObjectThreshold": 10000,
+ "defaultBackPressureDataSizeThreshold": "1 GB",
+ "scheduledState": "ENABLED",
+ "executionEngine": "INHERITED",
+ "maxConcurrentTasks": 1,
+ "statelessFlowTimeout": "1 min",
+ "flowFileConcurrency": "UNBOUNDED",
+ "flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
+ "componentType": "PROCESS_GROUP",
+ "groupIdentifier": "10b0aac8-4c39-3a71-807a-60128ba1ef34"
+ }
+ ],
+ "remoteProcessGroups": [],
+ "processors": [],
+ "inputPorts": [],
+ "outputPorts": [],
+ "connections": [],
+ "labels": [],
+ "funnels": [],
+ "controllerServices": [],
+ "defaultFlowFileExpiration": "0 sec",
+ "defaultBackPressureObjectThreshold": 10000,
+ "defaultBackPressureDataSizeThreshold": "1 GB",
+ "scheduledState": "ENABLED",
+ "executionEngine": "INHERITED",
+ "maxConcurrentTasks": 1,
+ "statelessFlowTimeout": "1 min",
+ "flowFileConcurrency": "UNBOUNDED",
+ "flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
+ "componentType": "PROCESS_GROUP"
+ }
+}
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/migrate-properties/flow.json
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/migrate-properties/flow.json
new file mode 100644
index 0000000000..69ba4d5399
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/flows/migrate-properties/flow.json
@@ -0,0 +1,695 @@
+{
+ "encodingVersion": {
+ "majorVersion": 2,
+ "minorVersion": 0
+ },
+ "maxTimerDrivenThreadCount": 10,
+ "registries": [],
+ "parameterContexts": [],
+ "parameterProviders": [],
+ "controllerServices": [],
+ "reportingTasks": [],
+ "flowAnalysisRules": [],
+ "rootGroup": {
+ "identifier": "10b0aac8-4c39-3a71-807a-60128ba1ef34",
+ "instanceIdentifier": "35e0b881-019a-1000-190e-b9f7878b3cad",
+ "name": "NiFi Flow",
+ "comments": "",
+ "position": {
+ "x": 0.0,
+ "y": 0.0
+ },
+ "processGroups": [
+ {
+ "identifier": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "instanceIdentifier": "c1a920de-019a-1000-6510-f3bca7dd9c69",
+ "name": "snapshot",
+ "comments": "",
+ "position": {
+ "x": -305.75,
+ "y": -385.75
+ },
+ "processGroups": [],
+ "remoteProcessGroups": [],
+ "processors": [
+ {
+ "identifier": "c1abdf6d-019a-1000-2d20-0e2dba89a292",
+ "instanceIdentifier": "0a622da4-8558-3409-f294-32010ae622ab",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "position": {
+ "x": -1168.0,
+ "y": -896.0
+ },
+ "type": "org.apache.nifi.processors.tests.system.CountFlowFiles",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "count-service": "c1a97022-019a-1000-4c72-79bb12714423"
+ },
+ "propertyDescriptors": {},
+ "style": {},
+ "schedulingPeriod": "0 sec",
+ "schedulingStrategy": "TIMER_DRIVEN",
+ "executionNode": "ALL",
+ "penaltyDuration": "30 sec",
+ "yieldDuration": "1 sec",
+ "bulletinLevel": "WARN",
+ "runDurationMillis": 0,
+ "concurrentlySchedulableTaskCount": 1,
+ "autoTerminatedRelationships": [],
+ "scheduledState": "ENABLED",
+ "retryCount": 10,
+ "retriedRelationships": [],
+ "backoffMechanism": "PENALIZE_FLOWFILE",
+ "maxBackoffPeriod": "10 mins",
+ "componentType": "PROCESSOR",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "f4ed9bc0-a7e5-3281-92a7-9dc2062ef51c",
+ "instanceIdentifier": "c1c4d1a2-019a-1000-6f39-378a0b7e670b",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "position": {
+ "x": -1672.0,
+ "y": -680.0
+ },
+ "type": "org.apache.nifi.processors.tests.system.CountFlowFiles",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "count-service": "c1a97022-019a-1000-4c72-79bb12714423"
+ },
+ "propertyDescriptors": {},
+ "style": {},
+ "schedulingPeriod": "0 sec",
+ "schedulingStrategy": "TIMER_DRIVEN",
+ "executionNode": "ALL",
+ "penaltyDuration": "30 sec",
+ "yieldDuration": "1 sec",
+ "bulletinLevel": "WARN",
+ "runDurationMillis": 0,
+ "concurrentlySchedulableTaskCount": 1,
+ "autoTerminatedRelationships": [
+ "success"
+ ],
+ "scheduledState": "ENABLED",
+ "retryCount": 10,
+ "retriedRelationships": [],
+ "backoffMechanism": "PENALIZE_FLOWFILE",
+ "maxBackoffPeriod": "10 mins",
+ "componentType": "PROCESSOR",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "786eeeb4-7026-327a-97de-c4cf3066d0da",
+ "instanceIdentifier": "c1aaf194-019a-1000-97b4-9de5c6038a2d",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "position": {
+ "x": -1672.0,
+ "y": -896.0
+ },
+ "type": "org.apache.nifi.processors.tests.system.CountFlowFiles",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "count-service": "c1a97022-019a-1000-4c72-79bb12714423"
+ },
+ "propertyDescriptors": {},
+ "style": {},
+ "schedulingPeriod": "0 sec",
+ "schedulingStrategy": "TIMER_DRIVEN",
+ "executionNode": "ALL",
+ "penaltyDuration": "30 sec",
+ "yieldDuration": "1 sec",
+ "bulletinLevel": "WARN",
+ "runDurationMillis": 0,
+ "concurrentlySchedulableTaskCount": 1,
+ "autoTerminatedRelationships": [],
+ "scheduledState": "ENABLED",
+ "retryCount": 10,
+ "retriedRelationships": [],
+ "backoffMechanism": "PENALIZE_FLOWFILE",
+ "maxBackoffPeriod": "10 mins",
+ "componentType": "PROCESSOR",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "c1abf8ce-019a-1000-3c4f-fb9ff2068e93",
+ "instanceIdentifier": "8712e667-3cf5-3bb9-0472-3dba5c99d00b",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "position": {
+ "x": -2224.0,
+ "y": -896.0
+ },
+ "type": "org.apache.nifi.processors.tests.system.CountFlowFiles",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "count-service": "c1a97022-019a-1000-4c72-79bb12714423"
+ },
+ "propertyDescriptors": {},
+ "style": {},
+ "schedulingPeriod": "0 sec",
+ "schedulingStrategy": "TIMER_DRIVEN",
+ "executionNode": "ALL",
+ "penaltyDuration": "30 sec",
+ "yieldDuration": "1 sec",
+ "bulletinLevel": "WARN",
+ "runDurationMillis": 0,
+ "concurrentlySchedulableTaskCount": 1,
+ "autoTerminatedRelationships": [],
+ "scheduledState": "ENABLED",
+ "retryCount": 10,
+ "retriedRelationships": [],
+ "backoffMechanism": "PENALIZE_FLOWFILE",
+ "maxBackoffPeriod": "10 mins",
+ "componentType": "PROCESSOR",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ }
+ ],
+ "inputPorts": [],
+ "outputPorts": [],
+ "connections": [
+ {
+ "identifier": "99ce85cb-2864-3eb1-b0ca-c2c3ab295e35",
+ "instanceIdentifier": "c1c53629-019a-1000-76d3-d440f14a6480",
+ "name": "",
+ "source": {
+ "id": "c1abf8ce-019a-1000-3c4f-fb9ff2068e93",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "8712e667-3cf5-3bb9-0472-3dba5c99d00b"
+ },
+ "destination": {
+ "id": "f4ed9bc0-a7e5-3281-92a7-9dc2062ef51c",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "c1c4d1a2-019a-1000-6f39-378a0b7e670b"
+ },
+ "labelIndex": 0,
+ "zIndex": 2,
+ "selectedRelationships": [
+ "success"
+ ],
+ "backPressureObjectThreshold": 10000,
+ "backPressureDataSizeThreshold": "1 GB",
+ "flowFileExpiration": "0 sec",
+ "prioritizers": [],
+ "bends": [],
+ "loadBalanceStrategy": "DO_NOT_LOAD_BALANCE",
+ "partitioningAttribute": "",
+ "loadBalanceCompression": "DO_NOT_COMPRESS",
+ "componentType": "CONNECTION",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "6a471e1d-32a8-34fc-95d6-cd30dba2b103",
+ "instanceIdentifier": "c1c4dc92-019a-1000-45fa-61adf7b9ee58",
+ "name": "",
+ "source": {
+ "id": "786eeeb4-7026-327a-97de-c4cf3066d0da",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "c1aaf194-019a-1000-97b4-9de5c6038a2d"
+ },
+ "destination": {
+ "id": "f4ed9bc0-a7e5-3281-92a7-9dc2062ef51c",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "c1c4d1a2-019a-1000-6f39-378a0b7e670b"
+ },
+ "labelIndex": 0,
+ "zIndex": 1,
+ "selectedRelationships": [
+ "success"
+ ],
+ "backPressureObjectThreshold": 10000,
+ "backPressureDataSizeThreshold": "1 GB",
+ "flowFileExpiration": "0 sec",
+ "prioritizers": [],
+ "bends": [],
+ "loadBalanceStrategy": "DO_NOT_LOAD_BALANCE",
+ "partitioningAttribute": "",
+ "loadBalanceCompression": "DO_NOT_COMPRESS",
+ "componentType": "CONNECTION",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "a2a51f78-cc69-36f6-bafc-e441e60ef6a4",
+ "instanceIdentifier": "c1e2bdec-019a-1000-d263-f93dd48054e8",
+ "name": "",
+ "source": {
+ "id": "c1abdf6d-019a-1000-2d20-0e2dba89a292",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "0a622da4-8558-3409-f294-32010ae622ab"
+ },
+ "destination": {
+ "id": "f4ed9bc0-a7e5-3281-92a7-9dc2062ef51c",
+ "type": "PROCESSOR",
+ "groupId": "f22b1174-292d-337a-8115-83282e1ef4d4",
+ "name": "CountFlowFiles",
+ "comments": "",
+ "instanceIdentifier": "c1c4d1a2-019a-1000-6f39-378a0b7e670b"
+ },
+ "labelIndex": 0,
+ "zIndex": 3,
+ "selectedRelationships": [
+ "success"
+ ],
+ "backPressureObjectThreshold": 10000,
+ "backPressureDataSizeThreshold": "1 GB",
+ "flowFileExpiration": "0 sec",
+ "prioritizers": [],
+ "bends": [],
+ "loadBalanceStrategy": "DO_NOT_LOAD_BALANCE",
+ "partitioningAttribute": "",
+ "loadBalanceCompression": "DO_NOT_COMPRESS",
+ "componentType": "CONNECTION",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ }
+ ],
+ "labels": [],
+ "funnels": [],
+ "controllerServices": [
+ {
+ "identifier": "405590bc-42ab-352b-8b4c-10b1295437bb",
+ "instanceIdentifier": "c1ee80be-019a-1000-7fd0-7ecf915c9eb6",
+ "name": "MigratePropertiesCountService-7",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "7"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "e6c0212a-ffeb-3479-ad45-6fc1906fbd87",
+ "instanceIdentifier": "c1eef06d-019a-1000-5923-def423e8e89b",
+ "name": "MigratePropertiesCountService-9",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "9"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "17f78983-e657-394c-9cd5-139edc287bfe",
+ "instanceIdentifier": "c1ee4d01-019a-1000-25d5-bcadd1cc2fbc",
+ "name": "MigratePropertiesCountService-6",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "6"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "e3ba5c31-d8e5-3d36-9d3c-2dc3f29d6371",
+ "instanceIdentifier": "c1ef2fd2-019a-1000-5814-e3b14cfd7185",
+ "name": "MigratePropertiesCountService-10",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "10"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "cf07376e-5c10-33b2-93d5-a9a4ee7c1c04",
+ "instanceIdentifier": "c1e6a9dd-019a-1000-99be-b7ea048419e6",
+ "name": "MigratePropertiesCountService-1",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "1"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "35881ce8-2803-3c0a-b38b-4c78a1d63d3a",
+ "instanceIdentifier": "c1a97022-019a-1000-4c72-79bb12714423",
+ "name": "MigratePropertiesCountService-0",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "0",
+ "count-service": "c1e6a9dd-019a-1000-99be-b7ea048419e6"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "4eff7e6a-7cfb-3869-b1bc-41a145d4f1ed",
+ "instanceIdentifier": "c1ef6d12-019a-1000-47a7-66a2e1fa14ed",
+ "name": "MigratePropertiesCountService-11",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "11"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "0f317a14-3462-3626-a64d-4228684dd344",
+ "instanceIdentifier": "c1eda538-019a-1000-b04f-ff355d6624fe",
+ "name": "MigratePropertiesCountService-3",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "3"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "04ec1f18-76bd-3d01-8317-7fccefea6e5c",
+ "instanceIdentifier": "c1ee16d6-019a-1000-eb16-178b7923f20f",
+ "name": "MigratePropertiesCountService-5",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "5"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "b6018d5e-1adb-38b2-9527-fe12638ba1ee",
+ "instanceIdentifier": "c1eddb74-019a-1000-eef7-db50e1ab98db",
+ "name": "MigratePropertiesCountService-4",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "4"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "e350d312-eb5d-3074-94f0-634de4384db2",
+ "instanceIdentifier": "c1ed6d0c-019a-1000-c334-064873c94518",
+ "name": "MigratePropertiesCountService-2",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "2"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ },
+ {
+ "identifier": "44b0e2cf-f2b6-31e0-8ae4-fb840d3651f0",
+ "instanceIdentifier": "c1eeb8d9-019a-1000-63b7-23f4e1eb2cdf",
+ "name": "MigratePropertiesCountService-8",
+ "comments": "",
+ "type":
"org.apache.nifi.cs.tests.system.MigratePropertiesCountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-nar",
+ "version": "2.7.0-SNAPSHOT"
+ },
+ "properties": {
+ "start-value": "8"
+ },
+ "propertyDescriptors": {},
+ "controllerServiceApis": [
+ {
+ "type": "org.apache.nifi.cs.tests.system.CountService",
+ "bundle": {
+ "group": "org.apache.nifi",
+ "artifact": "nifi-system-test-extensions-services-api-nar",
+ "version": "2.7.0-SNAPSHOT"
+ }
+ }
+ ],
+ "scheduledState": "ENABLED",
+ "bulletinLevel": "WARN",
+ "componentType": "CONTROLLER_SERVICE",
+ "groupIdentifier": "f22b1174-292d-337a-8115-83282e1ef4d4"
+ }
+ ],
+ "defaultFlowFileExpiration": "0 sec",
+ "defaultBackPressureObjectThreshold": 10000,
+ "defaultBackPressureDataSizeThreshold": "1 GB",
+ "scheduledState": "ENABLED",
+ "executionEngine": "INHERITED",
+ "maxConcurrentTasks": 1,
+ "statelessFlowTimeout": "1 min",
+ "flowFileConcurrency": "UNBOUNDED",
+ "flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
+ "componentType": "PROCESS_GROUP",
+ "groupIdentifier": "10b0aac8-4c39-3a71-807a-60128ba1ef34"
+ }
+ ],
+ "remoteProcessGroups": [],
+ "processors": [],
+ "inputPorts": [],
+ "outputPorts": [],
+ "connections": [],
+ "labels": [],
+ "funnels": [],
+ "controllerServices": [],
+ "defaultFlowFileExpiration": "0 sec",
+ "defaultBackPressureObjectThreshold": 10000,
+ "defaultBackPressureDataSizeThreshold": "1 GB",
+ "scheduledState": "ENABLED",
+ "executionEngine": "INHERITED",
+ "maxConcurrentTasks": 1,
+ "statelessFlowTimeout": "1 min",
+ "flowFileConcurrency": "UNBOUNDED",
+ "flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
+ "componentType": "PROCESS_GROUP"
+ }
+}