31c542d3a523312bcb3af95a64a79fa205fe0424
[dcaegen2/collectors/datafile.git] /
1 /*-
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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
13  * the License.
14  * ============LICENSE_END========================================================================
15  */
16
17 package org.onap.dcaegen2.collectors.datafile.configuration;
18
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.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.doReturn;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.times;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29
30 import ch.qos.logback.classic.spi.ILoggingEvent;
31 import ch.qos.logback.core.read.ListAppender;
32 import com.google.common.base.Charsets;
33 import com.google.common.io.Resources;
34 import com.google.gson.JsonElement;
35 import com.google.gson.JsonIOException;
36 import com.google.gson.JsonObject;
37 import com.google.gson.JsonParser;
38 import com.google.gson.JsonSyntaxException;
39 import java.io.ByteArrayInputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.InputStreamReader;
43 import java.net.URL;
44 import java.nio.charset.StandardCharsets;
45 import java.util.Map;
46 import java.util.Properties;
47 import org.junit.jupiter.api.Assertions;
48 import org.junit.jupiter.api.BeforeEach;
49 import org.junit.jupiter.api.Test;
50 import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
51 import org.onap.dcaegen2.collectors.datafile.model.logging.MappedDiagnosticContext;
52 import org.onap.dcaegen2.collectors.datafile.utils.LoggingUtils;
53 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.EnvProperties;
54 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.ImmutableEnvProperties;
55 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.providers.CloudConfigurationProvider;
56 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration;
57 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration;
58 import reactor.core.publisher.Flux;
59 import reactor.core.publisher.Mono;
60 import reactor.test.StepVerifier;
61
62 /**
63  * Tests the AppConfig.
64  *
65  * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18
66  * @author <a href="mailto:henrik.b.andersson@est.tech">Henrik Andersson</a>
67  */
68 class AppConfigTest {
69
70     private static final String CHANGE_IDENTIFIER = "PM_MEAS_FILES";
71
72
73     private static final ImmutableDmaapConsumerConfiguration CORRECT_DMAAP_CONSUMER_CONFIG = //
74             new ImmutableDmaapConsumerConfiguration.Builder() //
75                     .timeoutMs(-1) //
76                     .dmaapHostName("message-router.onap.svc.cluster.local") //
77                     .dmaapUserName("admin") //
78                     .dmaapUserPassword("admin") //
79                     .dmaapTopicName("events/unauthenticated.VES_NOTIFICATION_OUTPUT") //
80                     .dmaapPortNumber(2222) //
81                     .dmaapContentType("application/json") //
82                     .messageLimit(-1) //
83                     .dmaapProtocol("http") //
84                     .consumerId("C12") //
85                     .consumerGroup("OpenDcae-c12") //
86                     .trustStorePath("trustStorePath") //
87                     .trustStorePasswordPath("trustStorePasswordPath") //
88                     .keyStorePath("keyStorePath") //
89                     .keyStorePasswordPath("keyStorePasswordPath") //
90                     .enableDmaapCertAuth(true) //
91                     .build();
92
93     private static final ConsumerConfiguration CORRECT_CONSUMER_CONFIG = ImmutableConsumerConfiguration.builder() //
94             .topicUrl(
95                     "http://admin:admin@message-router.onap.svc.cluster.local:2222/events/unauthenticated.VES_NOTIFICATION_OUTPUT/OpenDcae-c12/C12")
96             .trustStorePath("trustStorePath") //
97             .trustStorePasswordPath("trustStorePasswordPath") //
98             .keyStorePath("keyStorePath") //
99             .keyStorePasswordPath("keyStorePasswordPath") //
100             .enableDmaapCertAuth(true) //
101             .build();
102
103     private static final PublisherConfiguration CORRECT_PUBLISHER_CONFIG = //
104             ImmutablePublisherConfiguration.builder() //
105                     .publishUrl("https://message-router.onap.svc.cluster.local:3907/publish/1") //
106                     .logUrl("https://dmaap.example.com/feedlog/972").trustStorePath("trustStorePath") //
107                     .trustStorePasswordPath("trustStorePasswordPath") //
108                     .keyStorePath("keyStorePath") //
109                     .keyStorePasswordPath("keyStorePasswordPath") //
110                     .enableDmaapCertAuth(true) //
111                     .changeIdentifier("PM_MEAS_FILES") //
112                     .userName("user") //
113                     .passWord("password") //
114                     .build();
115
116     private static final ImmutableFtpesConfig CORRECT_FTPES_CONFIGURATION = //
117             new ImmutableFtpesConfig.Builder() //
118                     .keyCert("/config/dfc.jks") //
119                     .keyPassword("secret") //
120                     .trustedCa("config/ftp.jks") //
121                     .trustedCaPassword("secret") //
122                     .build();
123
124     private static final ImmutableDmaapPublisherConfiguration CORRECT_DMAAP_PUBLISHER_CONFIG = //
125             new ImmutableDmaapPublisherConfiguration.Builder() //
126                     .dmaapTopicName("/publish/1") //
127                     .dmaapUserPassword("password") //
128                     .dmaapPortNumber(3907) //
129                     .dmaapProtocol("https") //
130                     .dmaapContentType("application/octet-stream") //
131                     .dmaapHostName("message-router.onap.svc.cluster.local") //
132                     .dmaapUserName("user") //
133                     .trustStorePath("trustStorePath") //
134                     .trustStorePasswordPath("trustStorePasswordPath") //
135                     .keyStorePath("keyStorePath") //
136                     .keyStorePasswordPath("keyStorePasswordPath") //
137                     .enableDmaapCertAuth(true) //
138                     .build();
139
140     private static EnvProperties properties() {
141         return ImmutableEnvProperties.builder() //
142                 .consulHost("host") //
143                 .consulPort(123) //
144                 .cbsName("cbsName") //
145                 .appName("appName") //
146                 .build();
147     }
148
149     private AppConfig appConfigUnderTest;
150     private CloudConfigurationProvider cloudConfigurationProvider = mock(CloudConfigurationProvider.class);
151     private final Map<String, String> context = MappedDiagnosticContext.initializeTraceContext();
152
153
154     @BeforeEach
155     public void setUp() {
156         appConfigUnderTest = spy(AppConfig.class);
157         appConfigUnderTest.setCloudConfigurationProvider(cloudConfigurationProvider);
158         appConfigUnderTest.systemEnvironment = new Properties();
159     }
160
161     @Test
162     public void whenTheConfigurationFits() throws IOException, DatafileTaskException {
163         // When
164         doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
165         appConfigUnderTest.initialize();
166
167         // Then
168         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
169
170         ConsumerConfiguration consumerCfg = appConfigUnderTest.getDmaapConsumerConfiguration();
171         Assertions.assertNotNull(consumerCfg);
172         assertThat(consumerCfg.toDmaap()).isEqualToComparingFieldByField(CORRECT_DMAAP_CONSUMER_CONFIG);
173         assertThat(consumerCfg).isEqualToComparingFieldByField(CORRECT_CONSUMER_CONFIG);
174
175         PublisherConfiguration publisherCfg = appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER);
176         Assertions.assertNotNull(publisherCfg);
177         assertThat(publisherCfg).isEqualToComparingFieldByField(CORRECT_PUBLISHER_CONFIG);
178         assertThat(publisherCfg.toDmaap()).isEqualToComparingFieldByField(CORRECT_DMAAP_PUBLISHER_CONFIG);
179
180         FtpesConfig ftpesConfig = appConfigUnderTest.getFtpesConfiguration();
181         assertThat(ftpesConfig).isNotNull();
182         assertThat(ftpesConfig).isEqualToComparingFieldByField(CORRECT_FTPES_CONFIGURATION);
183     }
184
185     @Test
186     public void whenTheConfigurationFits_twoProducers() throws IOException, DatafileTaskException {
187         // When
188         doReturn(getCorrectJsonTwoProducers()).when(appConfigUnderTest).createInputStream(any());
189         appConfigUnderTest.loadConfigurationFromFile();
190
191         // Then
192         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
193         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
194         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER));
195         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("XX_FILES"));
196         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("YY_FILES"));
197
198         assertThat(appConfigUnderTest.getPublisherConfiguration("XX_FILES").publishUrl())
199                 .isEqualTo("feed01::publish_url");
200         assertThat(appConfigUnderTest.getPublisherConfiguration("YY_FILES").publishUrl())
201                 .isEqualTo("feed01::publish_url");
202     }
203
204     @Test
205     public void whenFileIsNotExist_ThrowException() throws DatafileTaskException {
206         // Given
207         appConfigUnderTest.setFilepath("/temp.json");
208
209         ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
210
211         // When
212         appConfigUnderTest.loadConfigurationFromFile();
213
214         // Then
215         assertTrue("Error message missing in log.",
216                 logAppender.list.toString().contains("[WARN] Local configuration file not loaded: /temp.json"));
217         logAppender.stop();
218
219         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
220         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
221                 .hasMessageContaining("No PublishingConfiguration loaded, changeIdentifier: PM_MEAS_FILES");
222         Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
223     }
224
225     @Test
226     public void whenFileIsExistsButJsonIsIncorrect() throws IOException, DatafileTaskException {
227
228         // When
229         doReturn(getIncorrectJson()).when(appConfigUnderTest).createInputStream(any());
230         appConfigUnderTest.loadConfigurationFromFile();
231
232         // Then
233         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
234         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
235         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
236                 .hasMessageContaining(CHANGE_IDENTIFIER);
237         Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
238     }
239
240     @Test
241     public void whenTheConfigurationFits_ButRootElementIsNotAJsonObject() throws IOException, DatafileTaskException {
242
243         // When
244         doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
245         JsonElement jsonElement = mock(JsonElement.class);
246         when(jsonElement.isJsonObject()).thenReturn(false);
247         doReturn(jsonElement).when(appConfigUnderTest).getJsonElement(any(JsonParser.class), any(InputStream.class));
248         appConfigUnderTest.loadConfigurationFromFile();
249
250         // Then
251         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
252         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
253         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
254                 .hasMessageContaining(CHANGE_IDENTIFIER);
255         Assertions.assertNull(appConfigUnderTest.getFtpesConfiguration());
256     }
257
258     @Test
259     public void whenPeriodicConfigRefreshNoEnvironmentVariables() {
260         ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
261
262         Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
263
264         StepVerifier //
265                 .create(task) //
266                 .expectSubscription() //
267                 .expectNextCount(0) //
268                 .verifyComplete();
269
270         assertTrue(logAppender.list.toString().contains("$CONSUL_HOST environment has not been defined"));
271     }
272
273     @Test
274     public void whenPeriodicConfigRefreshNoConsul() {
275
276         doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
277         Mono<JsonObject> err = Mono.error(new IOException());
278         doReturn(err).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
279
280         ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
281         Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
282
283         StepVerifier //
284                 .create(task) //
285                 .expectSubscription() //
286                 .expectNextCount(0) //
287                 .verifyComplete();
288
289         assertTrue(logAppender.list.toString()
290                 .contains("Could not refresh application configuration java.io.IOException"));
291     }
292
293     @Test
294     public void whenPeriodicConfigRefreshSuccess() throws JsonIOException, JsonSyntaxException, IOException {
295         doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
296
297         Mono<JsonObject> json = Mono.just(getJsonRootObject());
298
299         doReturn(json, json).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
300
301         Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
302
303         StepVerifier //
304                 .create(task) //
305                 .expectSubscription() //
306                 .expectNext(appConfigUnderTest) //
307                 .verifyComplete();
308
309         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
310     }
311
312     @Test
313     public void whenPeriodicConfigRefreshSuccess2() throws JsonIOException, JsonSyntaxException, IOException {
314         doReturn(Mono.just(properties())).when(appConfigUnderTest).readEnvironmentVariables(any(), any());
315
316         Mono<JsonObject> json = Mono.just(getJsonRootObject());
317         Mono<JsonObject> err = Mono.error(new IOException()); // no config entry created by the dmaap plugin
318
319         doReturn(json, err).when(cloudConfigurationProvider).callForServiceConfigurationReactive(any());
320
321         Flux<AppConfig> task = appConfigUnderTest.createRefreshConfigurationTask(1L, context);
322
323         StepVerifier //
324                 .create(task) //
325                 .expectSubscription() //
326                 .expectNext(appConfigUnderTest) //
327                 .verifyComplete();
328
329         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
330     }
331
332     private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
333         JsonObject rootObject = (new JsonParser()).parse(new InputStreamReader(getCorrectJson())).getAsJsonObject();
334         return rootObject;
335     }
336
337     private static InputStream getCorrectJson() throws IOException {
338         URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test.json");
339         String string = Resources.toString(url, Charsets.UTF_8);
340         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
341     }
342
343     private static InputStream getCorrectJsonTwoProducers() throws IOException {
344         URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test_2producers.json");
345         String string = Resources.toString(url, Charsets.UTF_8);
346         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
347     }
348
349     private static InputStream getIncorrectJson() {
350         String string = "{" + //
351                 "    \"configs\": {" + //
352                 "        \"dmaap\": {"; //
353         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
354     }
355 }