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