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