2 * ============LICENSE_START======================================================================
3 * Copyright (C) 2018 NOKIA Intellectual Property, 2018-2019 Nordix Foundation. All rights reserved.
4 * ===============================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6 * in compliance with the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software distributed under the License
11 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 * or implied. See the License for the specific language governing permissions and limitations under
14 * ============LICENSE_END========================================================================
17 package org.onap.dcaegen2.collectors.datafile.configuration;
19 import static org.assertj.core.api.Assertions.assertThat;
20 import static org.assertj.core.api.Assertions.assertThatThrownBy;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.verifyNoMoreInteractions;
32 import static org.mockito.Mockito.when;
34 import ch.qos.logback.classic.spi.ILoggingEvent;
35 import ch.qos.logback.core.read.ListAppender;
36 import com.google.common.base.Charsets;
37 import com.google.common.io.Resources;
38 import com.google.gson.JsonElement;
39 import com.google.gson.JsonIOException;
40 import com.google.gson.JsonObject;
41 import com.google.gson.JsonParser;
42 import com.google.gson.JsonSyntaxException;
43 import java.io.ByteArrayInputStream;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.InputStreamReader;
48 import java.nio.charset.StandardCharsets;
49 import java.util.HashMap;
51 import java.util.Properties;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Test;
55 import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
56 import org.onap.dcaegen2.collectors.datafile.model.logging.MappedDiagnosticContext;
57 import org.onap.dcaegen2.collectors.datafile.utils.LoggingUtils;
58 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.EnvProperties;
59 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.ImmutableEnvProperties;
60 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.providers.CloudConfigurationProvider;
61 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration;
62 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration;
63 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration;
64 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration;
65 import reactor.core.Disposable;
66 import reactor.core.publisher.Flux;
67 import reactor.core.publisher.Mono;
68 import reactor.test.StepVerifier;
71 * Tests the AppConfig.
73 * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18
74 * @author <a href="mailto:henrik.b.andersson@est.tech">Henrik Andersson</a>
78 private static final String CHANGE_IDENTIFIER = "PM_MEAS_FILES";
80 private static final DmaapConsumerConfiguration CORRECT_DMAAP_CONSUMER_CONFIG = //
81 new ImmutableDmaapConsumerConfiguration.Builder() //
83 .dmaapHostName("message-router.onap.svc.cluster.local") //
84 .dmaapUserName("admin") //
85 .dmaapUserPassword("admin") //
86 .dmaapTopicName("events/unauthenticated.VES_NOTIFICATION_OUTPUT") //
87 .dmaapPortNumber(2222) //
88 .dmaapContentType("application/json") //
90 .dmaapProtocol("http") //
92 .consumerGroup("OpenDcae-c12") //
93 .trustStorePath("trustStorePath") //
94 .trustStorePasswordPath("trustStorePasswordPath") //
95 .keyStorePath("keyStorePath") //
96 .keyStorePasswordPath("keyStorePasswordPath") //
97 .enableDmaapCertAuth(true) //
100 private static final ConsumerConfiguration CORRECT_CONSUMER_CONFIG = ImmutableConsumerConfiguration.builder() //
102 "http://admin:admin@message-router.onap.svc.cluster.local:2222/events/unauthenticated.VES_NOTIFICATION_OUTPUT/OpenDcae-c12/C12")
103 .trustStorePath("trustStorePath") //
104 .trustStorePasswordPath("trustStorePasswordPath") //
105 .keyStorePath("keyStorePath") //
106 .keyStorePasswordPath("keyStorePasswordPath") //
107 .enableDmaapCertAuth(true) //
110 private static final PublisherConfiguration CORRECT_PUBLISHER_CONFIG = //
111 ImmutablePublisherConfiguration.builder() //
112 .publishUrl("https://message-router.onap.svc.cluster.local:3907/publish/1") //
113 .logUrl("https://dmaap.example.com/feedlog/972").trustStorePath("trustStorePath") //
114 .trustStorePasswordPath("trustStorePasswordPath") //
115 .keyStorePath("keyStorePath") //
116 .keyStorePasswordPath("keyStorePasswordPath") //
117 .enableDmaapCertAuth(true) //
118 .changeIdentifier("PM_MEAS_FILES") //
120 .passWord("password") //
123 private static final FtpesConfig CORRECT_FTPES_CONFIGURATION = //
124 new ImmutableFtpesConfig.Builder() //
125 .keyCert("/config/dfc.jks") //
126 .keyPassword("secret") //
127 .trustedCa("config/ftp.jks") //
128 .trustedCaPassword("secret") //
131 private static final DmaapPublisherConfiguration CORRECT_DMAAP_PUBLISHER_CONFIG = //
132 new ImmutableDmaapPublisherConfiguration.Builder() //
133 .dmaapTopicName("/publish/1") //
134 .dmaapUserPassword("password") //
135 .dmaapPortNumber(3907) //
136 .dmaapProtocol("https") //
137 .dmaapContentType("application/octet-stream") //
138 .dmaapHostName("message-router.onap.svc.cluster.local") //
139 .dmaapUserName("user") //
140 .trustStorePath("trustStorePath") //
141 .trustStorePasswordPath("trustStorePasswordPath") //
142 .keyStorePath("keyStorePath") //
143 .keyStorePasswordPath("keyStorePasswordPath") //
144 .enableDmaapCertAuth(true) //
147 private static EnvProperties properties() {
148 return ImmutableEnvProperties.builder() //
149 .consulHost("host") //
151 .cbsName("cbsName") //
152 .appName("appName") //
156 private AppConfig appConfigUnderTest;
157 private CloudConfigurationProvider cloudConfigurationProvider = mock(CloudConfigurationProvider.class);
158 private final Map<String, String> context = MappedDiagnosticContext.initializeTraceContext();
161 public void setUp() {
162 appConfigUnderTest = spy(AppConfig.class);
163 appConfigUnderTest.setCloudConfigurationProvider(cloudConfigurationProvider);
164 appConfigUnderTest.systemEnvironment = new Properties();
168 public void whenTheConfigurationFits() throws IOException, DatafileTaskException {
170 doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
171 appConfigUnderTest.initialize();
174 verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
176 ConsumerConfiguration consumerCfg = appConfigUnderTest.getDmaapConsumerConfiguration();
177 Assertions.assertNotNull(consumerCfg);
178 assertThat(consumerCfg.toDmaap()).isEqualToComparingFieldByField(CORRECT_DMAAP_CONSUMER_CONFIG);
179 assertThat(consumerCfg).isEqualToComparingFieldByField(CORRECT_CONSUMER_CONFIG);
181 PublisherConfiguration publisherCfg = appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER);
182 Assertions.assertNotNull(publisherCfg);
183 assertThat(publisherCfg).isEqualToComparingFieldByField(CORRECT_PUBLISHER_CONFIG);
184 assertThat(publisherCfg.toDmaap()).isEqualToComparingFieldByField(CORRECT_DMAAP_PUBLISHER_CONFIG);
186 FtpesConfig ftpesConfig = appConfigUnderTest.getFtpesConfiguration();
187 assertThat(ftpesConfig).isNotNull();
188 assertThat(ftpesConfig).isEqualToComparingFieldByField(CORRECT_FTPES_CONFIGURATION);
192 public void whenTheConfigurationFits_twoProducers() throws IOException, DatafileTaskException {
194 doReturn(getCorrectJsonTwoProducers()).when(appConfigUnderTest).createInputStream(any());
195 appConfigUnderTest.loadConfigurationFromFile();
198 verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
199 Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
200 Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER));
201 Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("XX_FILES"));
202 Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("YY_FILES"));
204 assertThat(appConfigUnderTest.getPublisherConfiguration("XX_FILES").publishUrl())
205 .isEqualTo("feed01::publish_url");
206 assertThat(appConfigUnderTest.getPublisherConfiguration("YY_FILES").publishUrl())
207 .isEqualTo("feed01::publish_url");
211 public void whenFileIsNotExist_ThrowException() throws DatafileTaskException {
213 appConfigUnderTest.setFilepath("/temp.json");
215 ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
218 appConfigUnderTest.loadConfigurationFromFile();
221 assertTrue("Error message missing in log.",
222 logAppender.list.toString().contains("[WARN] Local configuration file not loaded: /temp.json"));
225 Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
226 assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
227 .hasMessageContaining("No PublishingConfiguration loaded, changeIdentifier: PM_MEAS_FILES");
228 Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
232 public void whenFileIsExistsButJsonIsIncorrect() throws IOException, DatafileTaskException {
235 doReturn(getIncorrectJson()).when(appConfigUnderTest).createInputStream(any());
236 appConfigUnderTest.loadConfigurationFromFile();
239 verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
240 Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
241 assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
242 .hasMessageContaining(CHANGE_IDENTIFIER);
243 Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
247 public void whenTheConfigurationFits_ButRootElementIsNotAJsonObject() throws IOException, DatafileTaskException {
250 doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
251 JsonElement jsonElement = mock(JsonElement.class);
252 when(jsonElement.isJsonObject()).thenReturn(false);
253 doReturn(jsonElement).when(appConfigUnderTest).getJsonElement(any(JsonParser.class), any(InputStream.class));
254 appConfigUnderTest.loadConfigurationFromFile();
257 verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
258 Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
259 assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
260 .hasMessageContaining(CHANGE_IDENTIFIER);
261 Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
265 public void whenPeriodicConfigRefreshNoEnvironmentVariables() {
266 ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
268 Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
272 .expectSubscription() //
273 .expectNextCount(0) //
276 assertTrue(logAppender.list.toString().contains("$CONSUL_HOST environment has not been defined"));
280 public void whenPeriodicConfigRefreshNoConsul() {
282 doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
283 Mono<JsonObject> err = Mono.error(new IOException());
284 doReturn(err).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
286 ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
287 Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
291 .expectSubscription() //
292 .expectNextCount(0) //
296 logAppender.list.toString().contains("Could not refresh application configuration java.io.IOException"));
300 public void whenPeriodicConfigRefreshSuccess() throws JsonIOException, JsonSyntaxException, IOException {
301 doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
303 Mono<JsonObject> json = Mono.just(getJsonRootObject());
305 doReturn(json, json).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
307 Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
311 .expectSubscription() //
312 .expectNext(appConfigUnderTest) //
315 Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
319 public void whenPeriodicConfigRefreshSuccess2() throws JsonIOException, JsonSyntaxException, IOException {
320 doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
322 Mono<JsonObject> json = Mono.just(getJsonRootObject());
323 Mono<JsonObject> err = Mono.error(new IOException()); // no config entry created by the dmaap plugin
325 doReturn(json, err).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
327 Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
331 .expectSubscription() //
332 .expectNext(appConfigUnderTest) //
335 Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
339 public void whenStopSuccess() {
340 Disposable disposableMock = mock(Disposable.class);
341 appConfigUnderTest.refreshConfigTask = disposableMock;
343 appConfigUnderTest.stop();
345 verify(disposableMock).dispose();
346 verifyNoMoreInteractions(disposableMock);
347 assertNull(appConfigUnderTest.refreshConfigTask);
351 public void whenNoPublisherConfigurationThrowException() throws DatafileTaskException {
352 appConfigUnderTest.publishingConfigurations = new HashMap<>();
354 DatafileTaskException exception = assertThrows(DatafileTaskException.class,
355 () -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER));
356 assertEquals("Cannot find getPublishingConfiguration for changeIdentifier: " + CHANGE_IDENTIFIER,
357 exception.getMessage());
361 public void whenFeedIsConfiguredReturnTrue() {
362 HashMap<String, PublisherConfiguration> publishingConfigs = new HashMap<>();
363 publishingConfigs.put(CHANGE_IDENTIFIER, null);
364 appConfigUnderTest.publishingConfigurations = publishingConfigs;
366 assertTrue(appConfigUnderTest.isFeedConfigured(CHANGE_IDENTIFIER));
369 private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
370 JsonObject rootObject = (new JsonParser()).parse(new InputStreamReader(getCorrectJson())).getAsJsonObject();
374 private static InputStream getCorrectJson() throws IOException {
375 URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test.json");
376 String string = Resources.toString(url, Charsets.UTF_8);
377 return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
380 private static InputStream getCorrectJsonTwoProducers() throws IOException {
381 URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test_2producers.json");
382 String string = Resources.toString(url, Charsets.UTF_8);
383 return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
386 private static InputStream getIncorrectJson() {
387 String string = "{" + //
388 " \"configs\": {" + //
390 return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));