All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.nifi.minifi.StandardMiNiFiServer Maven / Gradle / Ivy

The newest version!
/*
 * 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.minifi;

import static java.util.Optional.ofNullable;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.nifi.minifi.validator.FlowValidator.validate;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.headless.HeadlessNiFiServer;
import org.apache.nifi.minifi.bootstrap.BootstrapListener;
import org.apache.nifi.minifi.c2.C2NifiClientService;
import org.apache.nifi.minifi.commons.api.MiNiFiProperties;
import org.apache.nifi.minifi.commons.status.FlowStatusReport;
import org.apache.nifi.minifi.status.StatusConfigReporter;
import org.apache.nifi.minifi.status.StatusRequestException;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StandardMiNiFiServer extends HeadlessNiFiServer implements MiNiFiServer {

    private static final Logger logger = LoggerFactory.getLogger(StandardMiNiFiServer.class);
    private static final String BOOTSTRAP_PORT_PROPERTY = "nifi.bootstrap.listen.port";
    private static final String LISTENER_BOOTSTRAP_PORT = "nifi.listener.bootstrap.port";

    private BootstrapListener bootstrapListener;
    private C2NifiClientService c2NifiClientService;

    @Override
    public void start() {
        super.start();

        initBootstrapListener();
        initC2();
        sendStartedStatus();
        startHeartbeat();
    }

    @Override
    protected void validateFlow() {
        List validationErrors = validate(getFlowController().getFlowManager());
        if (!validationErrors.isEmpty()) {
            logger.error("Validation errors found when loading the flow: {}", validationErrors);
            throw new IllegalStateException("Unable to start flow due to validation errors");
        }
        logger.info("Flow validated successfully");
    }

    @Override
    public void stop(boolean reload) {
        super.stop();
        if (bootstrapListener != null) {
            try {
                if (reload) {
                    bootstrapListener.reload();
                } else {
                    bootstrapListener.stop();
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
        if (c2NifiClientService != null) {
            c2NifiClientService.stop();
        }
    }

    public FlowStatusReport getStatusReport(String requestString) throws StatusRequestException {
        return StatusConfigReporter.getStatus(getFlowController(), requestString, logger);
    }

    private void initC2() {
        if (Boolean.parseBoolean(getNiFiProperties().getProperty(MiNiFiProperties.C2_ENABLE.getKey(), MiNiFiProperties.C2_ENABLE.getDefaultValue()))) {
            NiFiProperties niFiProperties = getNiFiProperties();
            enabledFlowIngestors(niFiProperties).ifPresentOrElse(
                flowIngestors -> {
                    logger.warn("Due to enabled flow ingestor(s) [{}] C2 client is not created. Please disable flow ingestors when using C2", flowIngestors);
                    c2NifiClientService = null;
                },
                () -> {
                    logger.info("C2 enabled, creating a C2 client instance");
                    c2NifiClientService = new C2NifiClientService(niFiProperties, getFlowController(), bootstrapListener, getFlowService());
                });
        } else {
            logger.debug("C2 Property [{}] missing or disabled: C2 client not created", MiNiFiProperties.C2_ENABLE.getKey());
            c2NifiClientService = null;
        }
    }

    private Optional enabledFlowIngestors(NiFiProperties niFiProperties) {
        return ofNullable(niFiProperties.getProperty(MiNiFiProperties.NIFI_MINIFI_NOTIFIER_INGESTORS.getKey(), EMPTY))
            .map(String::trim)
            .filter(StringUtils::isNotBlank);
    }

    private void startHeartbeat() {
        if (c2NifiClientService != null) {
            c2NifiClientService.start();
        }
    }

    private void initBootstrapListener() {
        String bootstrapPort = System.getProperty(BOOTSTRAP_PORT_PROPERTY);
        if (bootstrapPort != null) {
            try {
                int port = Integer.parseInt(bootstrapPort);

                if (port < 1 || port > 65535) {
                    throw new RuntimeException("Failed to start MiNiFi because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
                }

                bootstrapListener = new BootstrapListener(this, port);
                NiFiProperties niFiProperties = getNiFiProperties();

                // Default to 0 for random ephemeral port number
                final String listenerBootstrapPortProperty = niFiProperties.getProperty(LISTENER_BOOTSTRAP_PORT, "0");
                final int listenerBootstrapPort = Integer.parseInt(listenerBootstrapPortProperty);
                bootstrapListener.start(listenerBootstrapPort);
            } catch (IOException e) {
                throw new UncheckedIOException("Failed to start MiNiFi because of Bootstrap listener initialization error", e);
            } catch (NumberFormatException e) {
                throw new RuntimeException("Failed to start MiNiFi because system property '" + BOOTSTRAP_PORT_PROPERTY + "' is not a valid integer in the range 1 - 65535");
            }
        } else {
            logger.info("MiNiFi started without Bootstrap Port information provided; will not listen for requests from Bootstrap");
            bootstrapListener = null;
        }
    }

    private void sendStartedStatus() {
        if (bootstrapListener != null) {
            try {
                bootstrapListener.sendStartedStatus(true);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy