NIFI-10981 Ensure NarAutoLoader starts after provider retrieves NARs,… (#6785)

- NIFI-10981 Ensure NarAutoLoader starts after provider retrieves NARs, and ensure the auto-loader attempts to process any NARs available before starting to watch for new files
- Add system test with NAR Provider that copies NARs from a local directory and verifies the NARs were loaded and linked correctly
- Exclude new assembly from CI test-compile
This commit is contained in:
Bryan Bende 2022-12-16 11:30:37 -05:00 committed by GitHub
parent a8974253ce
commit 5c3ca9d537
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 900 additions and 13 deletions

View File

@ -54,6 +54,7 @@ env:
-pl -:nifi-stateless-processor-tests
-pl -:nifi-stateless-system-test-suite
-pl -:nifi-system-test-suite
-pl -:nifi-nar-provider-assembly
MAVEN_VERIFY_COMMAND: >-
mvn verify
--show-version

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ nb-configuration.xml
*~
.vscode/
.java-version

View File

@ -28,6 +28,8 @@ import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchService;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
@ -57,6 +59,14 @@ public class NarAutoLoader {
final File autoLoadDir = properties.getNarAutoLoadDirectory();
FileUtils.ensureDirectoryExistAndCanRead(autoLoadDir);
final List<File> initialNars = Arrays.asList(autoLoadDir.listFiles((dir, name) -> name.endsWith(".nar") && !name.startsWith(".")));
LOGGER.info("Found {} initial NARs from directory {}", initialNars.size(), autoLoadDir.getName());
if (!initialNars.isEmpty()) {
LOGGER.info("Loading initial NARs from directory {}...", autoLoadDir.getName());
narLoader.load(initialNars);
}
final WatchService watcher = FileSystems.getDefault().newWatchService();
final Path autoLoadPath = autoLoadDir.toPath();
autoLoadPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
@ -68,7 +78,7 @@ public class NarAutoLoader {
.narLoader(narLoader)
.build();
LOGGER.info("Starting NAR Auto-Loader for directory {} ...", new Object[]{autoLoadPath});
LOGGER.info("Starting NAR Auto-Loader Thread for directory {} ...", new Object[]{autoLoadPath});
final Thread autoLoaderThread = new Thread(narAutoLoaderTask);
autoLoaderThread.setName("NAR Auto-Loader");

View File

@ -49,9 +49,9 @@ import org.apache.nifi.nar.NarClassLoadersHolder;
import org.apache.nifi.nar.NarLoader;
import org.apache.nifi.nar.NarProvider;
import org.apache.nifi.nar.NarThreadContextClassLoader;
import org.apache.nifi.nar.NarUnpackMode;
import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.StandardNarLoader;
import org.apache.nifi.nar.NarUnpackMode;
import org.apache.nifi.security.util.TlsException;
import org.apache.nifi.services.FlowService;
import org.apache.nifi.ui.extension.UiExtension;
@ -788,6 +788,17 @@ public class JettyServer implements NiFiServer, ExtensionUiLoader {
DocGenerator.generate(props, extensionManager, extensionMapping);
// Additionally loaded NARs and collected flow resources must be in place before starting the flows
narProviderService = new ExternalResourceProviderServiceBuilder("NAR Auto-Loader Provider", extensionManager)
.providers(buildExternalResourceProviders(extensionManager, NAR_PROVIDER_PREFIX, descriptor -> descriptor.getLocation().toLowerCase().endsWith(".nar")))
.targetDirectory(new File(props.getProperty(NiFiProperties.NAR_LIBRARY_AUTOLOAD_DIRECTORY, NiFiProperties.DEFAULT_NAR_LIBRARY_AUTOLOAD_DIR)))
.conflictResolutionStrategy(props.getProperty(NAR_PROVIDER_CONFLICT_RESOLUTION, DEFAULT_NAR_PROVIDER_CONFLICT_RESOLUTION))
.pollInterval(props.getProperty(NAR_PROVIDER_POLL_INTERVAL_PROPERTY, DEFAULT_NAR_PROVIDER_POLL_INTERVAL))
.restrainingStartup(Boolean.valueOf(props.getProperty(NAR_PROVIDER_RESTRAIN_PROPERTY, "true")))
.build();
narProviderService.start();
// The NarAutoLoader must be started after the provider has started because we don't want the loader to load anything
// until all provided NARs are available, in case there is a dependency between any of the provided NARs
final NarUnpackMode unpackMode = props.isUnpackNarsToUberJar() ? NarUnpackMode.UNPACK_TO_UBER_JAR : NarUnpackMode.UNPACK_INDIVIDUAL_JARS;
final NarLoader narLoader = new StandardNarLoader(
props.getExtensionsWorkingDirectory(),
@ -801,15 +812,6 @@ public class JettyServer implements NiFiServer, ExtensionUiLoader {
narAutoLoader = new NarAutoLoader(props, narLoader);
narAutoLoader.start();
narProviderService = new ExternalResourceProviderServiceBuilder("NAR Auto-Loader Provider", extensionManager)
.providers(buildExternalResourceProviders(extensionManager, NAR_PROVIDER_PREFIX, descriptor -> descriptor.getLocation().toLowerCase().endsWith(".nar")))
.targetDirectory(new File(props.getProperty(NiFiProperties.NAR_LIBRARY_AUTOLOAD_DIRECTORY, NiFiProperties.DEFAULT_NAR_LIBRARY_AUTOLOAD_DIR)))
.conflictResolutionStrategy(props.getProperty(NAR_PROVIDER_CONFLICT_RESOLUTION, DEFAULT_NAR_PROVIDER_CONFLICT_RESOLUTION))
.pollInterval(props.getProperty(NAR_PROVIDER_POLL_INTERVAL_PROPERTY, DEFAULT_NAR_PROVIDER_POLL_INTERVAL))
.restrainingStartup(Boolean.getBoolean(props.getProperty(NAR_PROVIDER_RESTRAIN_PROPERTY, "true")))
.build();
narProviderService.start();
// start the server
server.start();

View File

@ -0,0 +1,67 @@
/*
* 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.nar.provider;
import org.apache.nifi.flow.resource.ExternalResourceDescriptor;
import org.apache.nifi.flow.resource.ExternalResourceProvider;
import org.apache.nifi.flow.resource.ExternalResourceProviderInitializationContext;
import org.apache.nifi.flow.resource.ImmutableExternalResourceDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
public class LocalDirectoryNarProvider implements ExternalResourceProvider {
private static final String SOURCE_DIR_PROPERTY = "source.dir";
private File sourceDir;
@Override
public void initialize(final ExternalResourceProviderInitializationContext context) {
final String sourceDirValue = context.getProperties().get(SOURCE_DIR_PROPERTY);
if (sourceDirValue == null) {
throw new IllegalStateException(SOURCE_DIR_PROPERTY + " is required");
}
sourceDir = new File(sourceDirValue);
if (!sourceDir.exists()) {
throw new IllegalStateException("Local NAR directory does not exist at: " + sourceDir.getAbsolutePath());
}
}
@Override
public Collection<ExternalResourceDescriptor> listResources() throws IOException {
return Arrays.stream(sourceDir.listFiles((dir, name) -> name.endsWith(".nar")))
.map(this::createDescriptor)
.collect(Collectors.toList());
}
private ExternalResourceDescriptor createDescriptor(final File file) {
return new ImmutableExternalResourceDescriptor(file.getName(), file.lastModified());
}
@Override
public InputStream fetchExternalResource(final ExternalResourceDescriptor descriptor) throws IOException {
final File file = new File(sourceDir, descriptor.getLocation());
return new FileInputStream(file);
}
}

View File

@ -0,0 +1,16 @@
# 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.
org.apache.nifi.nar.provider.LocalDirectoryNarProvider

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-assembly</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-processors-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>nifi-nar-provider-nars-${project.version}</finalName>
<attach>true</attach>
</configuration>
<executions>
<execution>
<id>make shared resource</id>
<goals>
<goal>single</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<archiverConfig>
<defaultDirectoryMode>0775</defaultDirectoryMode>
<directoryMode>0775</directoryMode>
<fileMode>0664</fileMode>
</archiverConfig>
<descriptors>
<descriptor>src/main/assembly/dependencies.xml</descriptor>
</descriptors>
<tarLongFileMode>posix</tarLongFileMode>
<formats>
<format>zip</format>
</formats>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<!--
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.
-->
<assembly>
<id>assembly</id>
<includeBaseDirectory>true</includeBaseDirectory>
<baseDirectory>nifi-nar-provider-nars</baseDirectory>
<dependencySets>
<dependencySet>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>./</outputDirectory>
<directoryMode>0770</directoryMode>
<fileMode>0664</fileMode>
<useTransitiveFiltering>true</useTransitiveFiltering>
</dependencySet>
</dependencySets>
</assembly>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-processors-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<packaging>nar</packaging>
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
<source.skip>true</source.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-processors</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-processors</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-utils</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-mock</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,94 @@
/*
* 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.nar.provider;
import org.apache.nifi.annotation.behavior.InputRequirement;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnScheduled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.ProcessorInitializationContext;
import org.apache.nifi.processor.Relationship;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Tags({"class-loader"})
@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
@CapabilityDescription("Gets ClassLoader info")
public class GetClassLoaderInfo extends AbstractProcessor {
public static final PropertyDescriptor CLASS_LOADER_INFO_SERVICE = new PropertyDescriptor.Builder()
.name("ClassLoader Info Service")
.description("Service for obtaining ClassLoader info")
.identifiesControllerService(ClassLoaderInfoService.class)
.required(true)
.build();
public static final Relationship SUCCESS_RELATIONSHIP = new Relationship.Builder()
.name("success")
.description("Example relationship")
.build();
private List<PropertyDescriptor> descriptors;
private Set<Relationship> relationships;
@Override
protected void init(final ProcessorInitializationContext context) {
descriptors = new ArrayList<>();
descriptors.add(CLASS_LOADER_INFO_SERVICE);
descriptors = Collections.unmodifiableList(descriptors);
relationships = new HashSet<>();
relationships.add(SUCCESS_RELATIONSHIP);
relationships = Collections.unmodifiableSet(relationships);
}
@Override
public Set<Relationship> getRelationships() {
return this.relationships;
}
@Override
public final List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return descriptors;
}
@OnScheduled
public void onScheduled(final ProcessContext context) {
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession session) {
final ClassLoaderInfoService classLoaderInfoService = context.getProperty(CLASS_LOADER_INFO_SERVICE).asControllerService(ClassLoaderInfoService.class);
final String classLoaderInfo = classLoaderInfoService.getClassLoaderString();
final FlowFile flowFile = session.create();
final FlowFile writtenFlowFile = session.write(flowFile, (out) -> out.write(classLoaderInfo.getBytes(StandardCharsets.UTF_8)));
session.transfer(writtenFlowFile, SUCCESS_RELATIONSHIP);
}
}

View File

@ -0,0 +1,15 @@
# 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.
org.apache.nifi.nar.provider.GetClassLoaderInfo

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-service-api-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<packaging>nar</packaging>
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
<source.skip>true</source.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-standard-services-api-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-service-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,29 @@
/*
* 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.nar.provider;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.controller.ControllerService;
@Tags({"class-loader"})
@CapabilityDescription("Obtains ClassLoader info.")
public interface ClassLoaderInfoService extends ControllerService {
String getClassLoaderString();
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-service-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<packaging>nar</packaging>
<properties>
<maven.javadoc.skip>true</maven.javadoc.skip>
<source.skip>true</source.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api-nar</artifactId>
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<artifactId>nifi-nar-provider-service</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-service-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-utils</artifactId>
<version>1.20.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-mock</artifactId>
<version>1.20.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,61 @@
/*
* 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.nar.provider;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnDisabled;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.reporting.InitializationException;
import java.util.Collections;
import java.util.List;
@Tags({"class-loader"})
@CapabilityDescription("Obtains ClassLoader info.")
public class StandardClassLoaderInfoService extends AbstractControllerService implements ClassLoaderInfoService {
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return Collections.emptyList();
}
/**
* @param context
* the configuration context
* @throws InitializationException
* if unable to create a database connection
*/
@OnEnabled
public void onEnabled(final ConfigurationContext context) throws InitializationException {
}
@OnDisabled
public void shutdown() {
}
@Override
public String getClassLoaderString() {
return Thread.currentThread().getContextClassLoader().getParent().getParent().toString();
}
}

View File

@ -0,0 +1,15 @@
# 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.
org.apache.nifi.nar.provider.StandardClassLoaderInfoService

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
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.
--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nifi-system-tests</artifactId>
<groupId>org.apache.nifi</groupId>
<version>1.20.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nifi-system-test-nar-provider-bundles</artifactId>
<packaging>pom</packaging>
<modules>
<module>nifi-nar-provider-service-api</module>
<module>nifi-nar-provider-service-api-nar</module>
<module>nifi-nar-provider-service</module>
<module>nifi-nar-provider-service-nar</module>
<module>nifi-nar-provider-processors</module>
<module>nifi-nar-provider-processors-nar</module>
<module>nifi-nar-provider-assembly</module>
</modules>
</project>

View File

@ -62,6 +62,24 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>extract-nar-provider-nars</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-test-resources</phase>
<configuration>
<includeArtifactIds>nifi-nar-provider-assembly</includeArtifactIds>
<excludeTransitive>true</excludeTransitive>
<outputDirectory>${project.build.directory}</outputDirectory>
<silent>true</silent>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
@ -211,7 +229,13 @@
<version>1.20.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-provider-assembly</artifactId>
<version>1.20.0-SNAPSHOT</version>
<classifier>assembly</classifier>
<type>zip</type>
</dependency>
<!-- dependencies for jaxb/activation/annotation for running NiFi on Java 11 -->
<!-- TODO: remove these once minimum Java version is 11 -->

View File

@ -77,6 +77,7 @@
<exclude>*:nifi-security-utils</exclude>
<exclude>*:nifi-security-utils-api</exclude>
<exclude>*:nifi-xml-processing</exclude>
<exclude>*:nifi-nar-provider-assembly</exclude>
<!-- exclude jaxb/activation/annotation libs from lib, they'll be included in the java11 subdir -->
<!-- TODO: remove these once minimum Java version is 11 -->

View File

@ -122,6 +122,12 @@ public class SpawnedStandaloneNiFiInstanceFactory implements NiFiInstanceFactory
final File destinationLib = new File(instanceDirectory, "lib");
copyContents(new File("target/nifi-lib-assembly/lib"), destinationLib);
final File destinationNarProviderNars = new File(instanceDirectory, "nifi-nar-provider-nars");
copyContents(new File("target/nifi-nar-provider-nars"), destinationNarProviderNars);
final File destinationExtensionsDir = new File(instanceDirectory, "extensions");
destinationExtensionsDir.mkdir();
final File destinationCertsDir = new File(instanceDirectory, "certs");
if (!destinationCertsDir.exists()) {
assertTrue(destinationCertsDir.mkdirs());

View File

@ -0,0 +1,82 @@
/*
* 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.nar;
import org.apache.nifi.tests.system.NiFiSystemIT;
import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
import org.apache.nifi.web.api.entity.ConnectionEntity;
import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class NarProviderAndAutoLoaderIT extends NiFiSystemIT {
private static final String ROOT_GROUP_ID = "root";
private static final String CLASSLOADER_INFO_SERVICE_NAR_ARTIFACT = "nifi-nar-provider-service-nar";
private static final String CLASSLOADER_INFO_SERVICE_CLASS_NAME = "org.apache.nifi.nar.provider.StandardClassLoaderInfoService";
private static final String CLASSLOADER_INFO_PROCESSOR_NAR_ARTIFACT = "nifi-nar-provider-processors-nar";
private static final String CLASSLOADER_INFO_PROCESSOR_CLASS_NAME = "org.apache.nifi.nar.provider.GetClassLoaderInfo";
private static final String EXPECTED_PARENT_CLASSLOADER = "nifi-nar-provider-service-api-nar-%s";
@Override
protected Map<String, String> getNifiPropertiesOverrides() {
final Map<String, String> properties = new HashMap<>();
properties.put("nifi.nar.library.provider.local-files.implementation", "org.apache.nifi.nar.provider.LocalDirectoryNarProvider");
properties.put("nifi.nar.library.provider.local-files.source.dir", "./nifi-nar-provider-nars");
return properties;
}
@Override
protected boolean isDestroyEnvironmentAfterEachTest() {
return true;
}
@Test
public void testProviedNarsLoadedAndLinkedCorrectly() throws IOException, NiFiClientException, InterruptedException {
final ControllerServiceEntity classLoaderInfoService = getClientUtil().createControllerService(CLASSLOADER_INFO_SERVICE_CLASS_NAME,
ROOT_GROUP_ID, NIFI_GROUP_ID, CLASSLOADER_INFO_SERVICE_NAR_ARTIFACT, getNiFiVersion());
getClientUtil().enableControllerService(classLoaderInfoService);
getClientUtil().waitForControllerSerivcesEnabled(classLoaderInfoService.getParentGroupId(), classLoaderInfoService.getId());
final ProcessorEntity getClassLoaderInfo = getClientUtil().createProcessor(CLASSLOADER_INFO_PROCESSOR_CLASS_NAME,
NIFI_GROUP_ID, CLASSLOADER_INFO_PROCESSOR_NAR_ARTIFACT, getNiFiVersion());
final Map<String, String> processorPropertiesForUpdate = new HashMap<>();
processorPropertiesForUpdate.put("ClassLoader Info Service", classLoaderInfoService.getId());
final ProcessorEntity updatedGetClassLoaderInfo = getClientUtil().updateProcessorProperties(getClassLoaderInfo, processorPropertiesForUpdate);
final ProcessorEntity terminateFlowFile = getClientUtil().createProcessor("TerminateFlowFile");
final ConnectionEntity connection = getClientUtil().createConnection(updatedGetClassLoaderInfo, terminateFlowFile, "success");
getNifiClient().getProcessorClient().runProcessorOnce(updatedGetClassLoaderInfo);
waitForQueueCount(connection.getId(), 1);
final String flowFileContent = getClientUtil().getFlowFileContentAsUtf8(connection.getId(), 0);
final String expectedParentClassLoader = String.format(EXPECTED_PARENT_CLASSLOADER, getNiFiVersion());
Assertions.assertTrue(flowFileContent.contains(expectedParentClassLoader));
}
}

View File

@ -27,7 +27,7 @@ java.arg.3=-Xmx512m
java.arg.14=-Djava.awt.headless=true
#java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8002
#java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8002
# Disable Logback web shutdown hook using System property
java.arg.logbackShutdown=-DlogbackDisableServletContainerInitializer=true

View File

@ -29,6 +29,7 @@
<module>nifi-system-test-extensions2-bundle</module>
<module>nifi-system-test-suite</module>
<module>nifi-stateless-system-test-suite</module>
<module>nifi-system-test-nar-provider-bundles</module>
</modules>
</project>