Repository: nifi-minifi Updated Branches: refs/heads/master 11f220d8d -> a1d2fd3fe
MINIFI-12 initial commit of http config change notifier This closes #13 Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi/commit/a1d2fd3f Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi/tree/a1d2fd3f Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi/diff/a1d2fd3f Branch: refs/heads/master Commit: a1d2fd3fe6b0b2cdd50394e2451aa10d5c9c81e9 Parents: 11f220d Author: Joseph Percivall <[email protected]> Authored: Thu Apr 14 19:01:54 2016 -0400 Committer: Joseph Percivall <[email protected]> Committed: Tue Apr 19 16:59:43 2016 -0400 ---------------------------------------------------------------------- .travis.yml | 2 - minifi-assembly/NOTICE | 7 +- minifi-bootstrap/pom.xml | 20 ++ .../configuration/RestChangeNotifier.java | 259 +++++++++++++++++++ .../configuration/TestRestChangeNotifier.java | 51 ++++ .../TestRestChangeNotifierSSL.java | 96 +++++++ .../configuration/util/MockChangeListener.java | 46 ++++ .../util/TestRestChangeNotifierCommon.java | 89 +++++++ .../src/test/resources/localhost-ks.jks | Bin 0 -> 3512 bytes .../src/test/resources/localhost-ts.jks | Bin 0 -> 1816 bytes .../src/test/resources/testUploadFile.txt | 18 ++ .../src/main/resources/conf/bootstrap.conf | 6 + pom.xml | 28 +- 13 files changed, 616 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/.travis.yml ---------------------------------------------------------------------- diff --git a/.travis.yml b/.travis.yml index b5c02d0..811a4c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ os: jdk: - oraclejdk8 - - oraclejdk7 - - openjdk7 # before_install aids in a couple workarounds for issues within the Travis-CI environment # 1. Workaround for buffer overflow issues with OpenJDK versions of java as per https://github.com/travis-ci/travis-ci/issues/5227#issuecomment-165135711 http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-assembly/NOTICE ---------------------------------------------------------------------- diff --git a/minifi-assembly/NOTICE b/minifi-assembly/NOTICE index 90163f2..e7f6169 100644 --- a/minifi-assembly/NOTICE +++ b/minifi-assembly/NOTICE @@ -13,4 +13,9 @@ The following binary components are provided under the Apache Software License v (ASLv2) Apache NiFi The following NOTICE information applies: Apache NiFi - Copyright 2014-2016 The Apache Software Foundation \ No newline at end of file + Copyright 2014-2016 The Apache Software Foundation + + (ASLv2) Jetty + The following NOTICE information applies: + Jetty Web Container + Copyright 1995-2015 Mort Bay Consulting Pty Ltd. \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/pom.xml ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/pom.xml b/minifi-bootstrap/pom.xml index 68bc60a..2616190 100644 --- a/minifi-bootstrap/pom.xml +++ b/minifi-bootstrap/pom.xml @@ -56,6 +56,26 @@ limitations under the License. </dependency> <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>okhttp</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.nifi</groupId> <artifactId>nifi-framework-core</artifactId> <version>0.6.0</version> http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java new file mode 100644 index 0000000..5807f89 --- /dev/null +++ b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java @@ -0,0 +1,259 @@ +/* + * 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.bootstrap.configuration; + +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URI; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +import static org.apache.nifi.minifi.bootstrap.RunMiNiFi.NOTIFIER_PROPERTY_PREFIX; + + +public class RestChangeNotifier implements ConfigurationChangeNotifier { + + private final Set<ConfigurationChangeListener> configurationChangeListeners = new HashSet<>(); + private final static Logger logger = LoggerFactory.getLogger(RestChangeNotifier.class); + private String configFile = null; + private final Server jetty; + public static final String GET_TEXT = "This is a config change listener for an Apache NiFi - MiNiFi instance.\n" + + "Use this rest server to upload a conf.yml to configure the MiNiFi instance.\n" + + "Send a POST http request to '/' to upload the file."; + public static final String POST_TEXT ="Configuration received, notifying listeners.\n"; + public static final String OTHER_TEXT ="This is not a support HTTP operation. Please use GET to get more information or POST to upload a new config.yml file.\n"; + + + public static final String POST = "POST"; + public static final String GET = "GET"; + + public static final String PORT_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.port"; + public static final String HOST_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.host"; + public static final String TRUSTSTORE_LOCATION_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.location"; + public static final String TRUSTSTORE_PASSWORD_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.password"; + public static final String TRUSTSTORE_TYPE_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.type"; + public static final String KEYSTORE_LOCATION_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.location"; + public static final String KEYSTORE_PASSWORD_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.password"; + public static final String KEYSTORE_TYPE_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.type"; + public static final String NEED_CLIENT_AUTH_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.need.client.auth"; + + public RestChangeNotifier(){ + QueuedThreadPool queuedThreadPool = new QueuedThreadPool(); + queuedThreadPool.setDaemon(true); + jetty = new Server(queuedThreadPool); + } + + @Override + public void initialize(Properties properties) { + logger.info("Initializing"); + + // create the secure connector if keystore location is specified + if (properties.getProperty(KEYSTORE_LOCATION_KEY) != null) { + createSecureConnector(properties); + } else { + // create the unsecure connector otherwise + createConnector(properties); + } + + HandlerCollection handlerCollection = new HandlerCollection(true); + handlerCollection.addHandler(new JettyHandler()); + jetty.setHandler(handlerCollection); + } + + + @Override + public Set<ConfigurationChangeListener> getChangeListeners() { + return configurationChangeListeners; + } + + @Override + public boolean registerListener(ConfigurationChangeListener listener) { + return configurationChangeListeners.add(listener); + } + + @Override + public void notifyListeners() { + if (configFile == null){ + throw new IllegalStateException("Attempting to notify listeners when there is no new config file."); + } + + for (final ConfigurationChangeListener listener : getChangeListeners()) { + try (final ByteArrayInputStream fis = new ByteArrayInputStream(configFile.getBytes());) { + listener.handleChange(fis); + } catch (IOException ex) { + throw new IllegalStateException("Unable to read the changed file " + configFile, ex); + } + } + + configFile = null; + } + + @Override + public void start(){ + try { + jetty.start(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + + @Override + public void close() throws IOException { + logger.warn("Shutting down the jetty server"); + try { + jetty.stop(); + jetty.destroy(); + } catch (Exception e) { + throw new IOException(e); + } + logger.warn("Done shutting down the jetty server"); + } + + public URI getURI(){ + return jetty.getURI(); + } + + public int getPort(){ + if (!jetty.isStarted()) { + throw new IllegalStateException("Jetty server not started"); + } + return ((ServerConnector) jetty.getConnectors()[0]).getLocalPort(); + } + + public String getConfigString(){ + return configFile; + } + + private void setConfigFile(String configFile){ + this.configFile = configFile; + } + + private void createConnector(Properties properties) { + final ServerConnector http = new ServerConnector(jetty); + + http.setPort(Integer.parseInt(properties.getProperty(PORT_KEY, "0"))); + http.setHost(properties.getProperty(HOST_KEY, "localhost")); + + // Severely taxed or distant environments may have significant delays when executing. + http.setIdleTimeout(30000L); + jetty.addConnector(http); + + logger.info("Added an http connector on the host '{}' and port '{}'", new Object[]{http.getHost(), http.getPort()}); + } + + private void createSecureConnector(Properties properties) { + SslContextFactory ssl = new SslContextFactory(); + + if (properties.getProperty(KEYSTORE_LOCATION_KEY) != null) { + ssl.setKeyStorePath(properties.getProperty(KEYSTORE_LOCATION_KEY)); + ssl.setKeyStorePassword(properties.getProperty(KEYSTORE_PASSWORD_KEY)); + ssl.setKeyStoreType(properties.getProperty(KEYSTORE_TYPE_KEY)); + } + + if (properties.getProperty(TRUSTSTORE_LOCATION_KEY) != null) { + ssl.setTrustStorePath(properties.getProperty(TRUSTSTORE_LOCATION_KEY)); + ssl.setTrustStorePassword(properties.getProperty(TRUSTSTORE_PASSWORD_KEY)); + ssl.setTrustStoreType(properties.getProperty(TRUSTSTORE_TYPE_KEY)); + ssl.setNeedClientAuth(Boolean.parseBoolean(properties.getProperty(NEED_CLIENT_AUTH_KEY, "true"))); + } + + // build the connector + final ServerConnector https = new ServerConnector(jetty, ssl); + + // set host and port + https.setPort(Integer.parseInt(properties.getProperty(PORT_KEY,"0"))); + https.setHost(properties.getProperty(HOST_KEY, "localhost")); + + // Severely taxed environments may have significant delays when executing. + https.setIdleTimeout(30000L); + + // add the connector + jetty.addConnector(https); + + logger.info("Added an https connector on the host '{}' and port '{}'", new Object[]{https.getHost(), https.getPort()}); + } + + + public class JettyHandler extends AbstractHandler { + + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + + logRequest(request); + + baseRequest.setHandled(true); + + if(POST.equals(request.getMethod())) { + final StringBuilder configBuilder = new StringBuilder(); + BufferedReader reader = request.getReader(); + if(reader != null && reader.ready()){ + String line; + while ((line = reader.readLine()) != null) { + configBuilder.append(line); + configBuilder.append(System.getProperty("line.separator")); + } + } + setConfigFile(configBuilder.substring(0,configBuilder.length()-1)); + notifyListeners(); + writeOutput(response, POST_TEXT, 200); + } else if(GET.equals(request.getMethod())) { + writeOutput(response, GET_TEXT, 200); + } else { + writeOutput(response, OTHER_TEXT, 404); + } + } + + private void writeOutput(HttpServletResponse response, String responseText, int responseCode) throws IOException { + response.setStatus(responseCode); + response.setContentType("text/plain"); + response.setContentLength(responseText.length()); + try (PrintWriter writer = response.getWriter()) { + writer.print(responseText); + writer.flush(); + } + } + + private void logRequest(HttpServletRequest request){ + logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + logger.info("request method = " + request.getMethod()); + logger.info("request url = " + request.getRequestURL()); + logger.info("context path = " + request.getContextPath()); + logger.info("request content type = " + request.getContentType()); + logger.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); + } + + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java new file mode 100644 index 0000000..75b44e3 --- /dev/null +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java @@ -0,0 +1,51 @@ +/* + * 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.bootstrap.configuration; + + +import com.squareup.okhttp.OkHttpClient; +import org.apache.nifi.minifi.bootstrap.configuration.util.TestRestChangeNotifierCommon; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.net.MalformedURLException; +import java.util.Properties; + + +public class TestRestChangeNotifier extends TestRestChangeNotifierCommon { + + @BeforeClass + public static void setUp() throws InterruptedException, MalformedURLException { + Properties properties = new Properties(); + restChangeNotifier = new RestChangeNotifier(); + restChangeNotifier.initialize(properties); + restChangeNotifier.registerListener(mockChangeListener); + restChangeNotifier.start(); + + client = new OkHttpClient(); + + url = restChangeNotifier.getURI().toURL().toString(); + Thread.sleep(1000); + } + + @AfterClass + public static void stop() throws Exception { + restChangeNotifier.close(); + client = null; + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java new file mode 100644 index 0000000..908e693 --- /dev/null +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.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.minifi.bootstrap.configuration; + + +import com.squareup.okhttp.OkHttpClient; +import org.apache.nifi.minifi.bootstrap.configuration.util.TestRestChangeNotifierCommon; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.Properties; + + +public class TestRestChangeNotifierSSL extends TestRestChangeNotifierCommon { + + + @BeforeClass + public static void setUpHttps() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, UnrecoverableKeyException, KeyManagementException, InterruptedException { + Properties properties = new Properties(); + properties.setProperty(RestChangeNotifier.TRUSTSTORE_LOCATION_KEY, "./src/test/resources/localhost-ts.jks"); + properties.setProperty(RestChangeNotifier.TRUSTSTORE_PASSWORD_KEY, "localtest"); + properties.setProperty(RestChangeNotifier.TRUSTSTORE_TYPE_KEY, "JKS"); + properties.setProperty(RestChangeNotifier.KEYSTORE_LOCATION_KEY, "./src/test/resources/localhost-ks.jks"); + properties.setProperty(RestChangeNotifier.KEYSTORE_PASSWORD_KEY, "localtest"); + properties.setProperty(RestChangeNotifier.KEYSTORE_TYPE_KEY, "JKS"); + properties.setProperty(RestChangeNotifier.NEED_CLIENT_AUTH_KEY, "true"); + restChangeNotifier = new RestChangeNotifier(); + restChangeNotifier.initialize(properties); + restChangeNotifier.registerListener(mockChangeListener); + restChangeNotifier.start(); + + client = new OkHttpClient(); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(readKeyStore("./src/test/resources/localhost-ts.jks")); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(readKeyStore("./src/test/resources/localhost-ks.jks"), "localtest".toCharArray()); + + sslContext.init(keyManagerFactory.getKeyManagers(),trustManagerFactory.getTrustManagers(), new SecureRandom()); + client.setSslSocketFactory(sslContext.getSocketFactory()); + + url = restChangeNotifier.getURI().toURL().toString(); + Thread.sleep(1000); + } + + @AfterClass + public static void stop() throws Exception { + restChangeNotifier.close(); + client = null; + } + + private static KeyStore readKeyStore(String path) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + + char[] password = "localtest".toCharArray(); + + java.io.FileInputStream fis = null; + try { + fis = new java.io.FileInputStream(path); + ks.load(fis, password); + } finally { + if (fis != null) { + fis.close(); + } + } + return ks; + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java new file mode 100644 index 0000000..6843889 --- /dev/null +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java @@ -0,0 +1,46 @@ +/* + * 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.bootstrap.configuration.util; + +import org.apache.commons.io.IOUtils; +import org.apache.nifi.minifi.bootstrap.configuration.ConfigurationChangeListener; + +import java.io.IOException; +import java.io.InputStream; + +public class MockChangeListener implements ConfigurationChangeListener { + String confFile; + + @Override + public void handleChange(InputStream inputStream) { + try { + confFile = IOUtils.toString(inputStream, "UTF-8"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public String getConfFile() { + return confFile; + } + + public void setConfFile(String confFile) { + this.confFile = confFile; + } + +} http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java new file mode 100644 index 0000000..b3c4f54 --- /dev/null +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java @@ -0,0 +1,89 @@ +/* + * 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.bootstrap.configuration.util; + +import com.squareup.okhttp.Headers; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; +import org.apache.nifi.minifi.bootstrap.configuration.RestChangeNotifier; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class TestRestChangeNotifierCommon { + + public static OkHttpClient client; + public static RestChangeNotifier restChangeNotifier; + public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); + public static String url; + public static MockChangeListener mockChangeListener = new MockChangeListener(); + + @Test + public void testGet() throws Exception { + assertEquals(1, restChangeNotifier.getChangeListeners().size()); + + Request request = new Request.Builder() + .url(url) + .build(); + + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + + Headers responseHeaders = response.headers(); + for (int i = 0; i < responseHeaders.size(); i++) { + System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); + } + + assertEquals(RestChangeNotifier.GET_TEXT, response.body().string()); + } + + @Test + public void testFileUpload() throws Exception { + assertEquals(1, restChangeNotifier.getChangeListeners().size()); + + File file = new File("src/test/resources/testUploadFile.txt"); + assertTrue(file.exists()); + assertTrue(file.canRead()); + + Request request = new Request.Builder() + .url(url) + .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)) + .addHeader("charset","UTF-8") + .build(); + + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + + Headers responseHeaders = response.headers(); + for (int i = 0; i < responseHeaders.size(); i++) { + System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); + } + + assertEquals(RestChangeNotifier.POST_TEXT, response.body().string()); + + assertEquals(new String(Files.readAllBytes(file.toPath())), mockChangeListener.getConfFile()); + } +} http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/localhost-ks.jks ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/resources/localhost-ks.jks b/minifi-bootstrap/src/test/resources/localhost-ks.jks new file mode 100755 index 0000000..df36197 Binary files /dev/null and b/minifi-bootstrap/src/test/resources/localhost-ks.jks differ http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/localhost-ts.jks ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/resources/localhost-ts.jks b/minifi-bootstrap/src/test/resources/localhost-ts.jks new file mode 100755 index 0000000..7824378 Binary files /dev/null and b/minifi-bootstrap/src/test/resources/localhost-ts.jks differ http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/testUploadFile.txt ---------------------------------------------------------------------- diff --git a/minifi-bootstrap/src/test/resources/testUploadFile.txt b/minifi-bootstrap/src/test/resources/testUploadFile.txt new file mode 100644 index 0000000..cbd1af8 --- /dev/null +++ b/minifi-bootstrap/src/test/resources/testUploadFile.txt @@ -0,0 +1,18 @@ +/* + * 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. + */ + + this is a test upload file created to test the RestChangeListener \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf ---------------------------------------------------------------------- diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf index c9626da..107d9cc 100644 --- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf +++ b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf @@ -33,6 +33,7 @@ nifi.minifi.config=./conf/config.yml # Notifiers to use for the associated agent, comma separated list of class names #nifi.minifi.notifier.components=org.apache.nifi.minifi.bootstrap.configuration.FileChangeNotifier +#nifi.minifi.notifier.components=org.apache.nifi.minifi.bootstrap.configuration.RestChangeNotifier # File change notifier configuration @@ -41,6 +42,11 @@ nifi.minifi.config=./conf/config.yml # How frequently the file specified by 'nifi.minifi.notifier.file.config.path' should be evaluated for changes. #nifi.minifi.notifier.file.polling.period.seconds=5 +# Rest change notifier configuration + +# Port on which the Jetty server will bind to, keep commented for a random open port +#nifi.minifi.notifier.http.port=8338 + # Disable JSR 199 so that we can use JSP's without running a JDK java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index cdd8357..b765c7f 100644 --- a/pom.xml +++ b/pom.xml @@ -86,14 +86,15 @@ limitations under the License. <url>https://issues.apache.org/jira/browse/MINIFI</url> </issueManagement> <properties> - <maven.compiler.source>1.7</maven.compiler.source> - <maven.compiler.target>1.7</maven.compiler.target> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> <maven.min-version>3.1.0</maven.min-version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <inceptionYear>2016</inceptionYear> <org.slf4j.version>1.7.12</org.slf4j.version> <org.apache.nifi.version>0.6.0</org.apache.nifi.version> + <jetty.version>9.3.8.v20160314</jetty.version> </properties> <dependencies> @@ -177,6 +178,16 @@ limitations under the License. <version>${org.slf4j.version}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> <!-- NiFi Modules --> <dependency> @@ -368,7 +379,18 @@ limitations under the License. <artifactId>slf4j-simple</artifactId> <version>${org.slf4j.version}</version> </dependency> - + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>okhttp</artifactId> + <version>2.7.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + <scope>test</scope> + </dependency> </dependencies> </dependencyManagement>
