bcbe7f82ba187461efd646dd93be40967c435211
[dcaegen2/collectors/datafile.git] /
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2018, 2020-2021 NOKIA Intellectual Property, 2018-2019 Nordix Foundation.
4  * All rights reserved.
5  * ===============================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7  * in compliance with the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software distributed under the License
12  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing permissions and limitations under
14  * the License.
15  * ============LICENSE_END========================================================================
16  */
17
18 package org.onap.dcaegen2.collectors.datafile.configuration;
19
20 import ch.qos.logback.classic.spi.ILoggingEvent;
21 import ch.qos.logback.core.read.ListAppender;
22 import com.google.common.base.Charsets;
23 import com.google.common.io.Resources;
24 import com.google.gson.JsonElement;
25 import com.google.gson.JsonIOException;
26 import com.google.gson.JsonObject;
27 import com.google.gson.JsonParser;
28 import com.google.gson.JsonSyntaxException;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
33 import org.onap.dcaegen2.collectors.datafile.model.logging.MappedDiagnosticContext;
34 import org.onap.dcaegen2.collectors.datafile.utils.LoggingUtils;
35 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient;
36 import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration;
37 import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest;
38 import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys;
39 import reactor.core.publisher.Flux;
40 import reactor.core.publisher.Mono;
41 import reactor.test.StepVerifier;
42
43 import java.io.ByteArrayInputStream;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.InputStreamReader;
47 import java.net.URL;
48 import java.nio.charset.StandardCharsets;
49 import java.util.Map;
50 import java.util.Properties;
51
52 import static org.assertj.core.api.Assertions.assertThat;
53 import static org.assertj.core.api.Assertions.assertThatThrownBy;
54 import static org.junit.jupiter.api.Assertions.assertTrue;
55 import static org.mockito.ArgumentMatchers.any;
56 import static org.mockito.Mockito.doReturn;
57 import static org.mockito.Mockito.mock;
58 import static org.mockito.Mockito.spy;
59 import static org.mockito.Mockito.times;
60 import static org.mockito.Mockito.verify;
61 import static org.mockito.Mockito.when;
62
63 /**
64  * Tests the AppConfig.
65  *
66  * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18
67  * @author <a href="mailto:henrik.b.andersson@est.tech">Henrik Andersson</a>
68  */
69 public class AppConfigTest {
70
71     public static final String CHANGE_IDENTIFIER = "PM_MEAS_FILES";
72
73     private static final PublisherConfiguration CORRECT_PUBLISHER_CONFIG = //
74         ImmutablePublisherConfiguration.builder() //
75             .publishUrl("https://localhost:3907/publish/1") //
76             .logUrl("https://localhost:3907/feedlog/1") //
77             .trustStorePath("src/test/resources/trust.jks") //
78             .trustStorePasswordPath("src/test/resources/trust.pass") //
79             .keyStorePath("src/test/resources/cert.jks") //
80             .keyStorePasswordPath("src/test/resources/jks.pass") //
81             .enableDmaapCertAuth(true) //
82             .changeIdentifier("PM_MEAS_FILES") //
83             .userName("CYE9fl40") //
84             .password("izBJD8nLjawq0HMG") //
85             .build();
86
87     private static final ImmutableCertificateConfig CORRECT_CERTIFICATE_CONFIGURATION = //
88         new ImmutableCertificateConfig.Builder() //
89             .keyCert("/src/test/resources/dfc.jks") //
90             .keyPasswordPath("/src/test/resources/dfc.jks.pass") //
91             .trustedCa("/src/test/resources/cert.jks") //
92             .trustedCaPasswordPath("/src/test/resources/cert.jks.pass") //
93             .build();
94
95     private AppConfig appConfigUnderTest;
96     private final Map<String, String> context = MappedDiagnosticContext.initializeTraceContext();
97     CbsClient cbsClient = mock(CbsClient.class);
98     CbsClientConfiguration cbsClientConfiguration = mock(CbsClientConfiguration.class);
99
100     @BeforeEach
101     void setUp() {
102         appConfigUnderTest = spy(AppConfig.class);
103         appConfigUnderTest.systemEnvironment = new Properties();
104
105     }
106
107     @Test
108     public void whenTheConfigurationFits() throws IOException, DatafileTaskException {
109         // When
110         doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
111         appConfigUnderTest.initialize();
112
113         // Then
114         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
115
116         ConsumerConfiguration consumerCfg = appConfigUnderTest.getDmaapConsumerConfiguration();
117         Assertions.assertNotNull(consumerCfg);
118         assertThat(consumerCfg).satisfies(this::checkCorrectConsumerConfiguration);
119
120         PublisherConfiguration publisherCfg = appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER);
121         Assertions.assertNotNull(publisherCfg);
122         assertThat(publisherCfg).isEqualToComparingFieldByField(CORRECT_PUBLISHER_CONFIG);
123
124         CertificateConfig certificateConfig = appConfigUnderTest.getCertificateConfiguration();
125         assertThat(certificateConfig).isNotNull();
126         assertThat(certificateConfig).isEqualToComparingFieldByField(CORRECT_CERTIFICATE_CONFIGURATION);
127     }
128
129     @Test
130     public void whenTheConfigurationFits_twoProducers() throws IOException, DatafileTaskException {
131         // When
132         doReturn(getCorrectJsonTwoProducers()).when(appConfigUnderTest).createInputStream(any());
133         appConfigUnderTest.loadConfigurationFromFile();
134
135         // Then
136         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
137         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
138         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER));
139         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("XX_FILES"));
140         Assertions.assertNotNull(appConfigUnderTest.getPublisherConfiguration("YY_FILES"));
141
142         assertThat(appConfigUnderTest.getPublisherConfiguration("XX_FILES").publishUrl())
143             .isEqualTo("feed01::publish_url");
144         assertThat(appConfigUnderTest.getPublisherConfiguration("YY_FILES").publishUrl())
145             .isEqualTo("feed01::publish_url");
146     }
147
148     @Test
149     public void whenFileIsNotExist_ThrowException() throws DatafileTaskException {
150         // Given
151         appConfigUnderTest.setFilepath("/temp.json");
152
153         // When
154         appConfigUnderTest.loadConfigurationFromFile();
155
156         // Then
157         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
158         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
159             .hasMessageContaining("No PublishingConfiguration loaded, changeIdentifier: PM_MEAS_FILES");
160
161         Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration());
162     }
163
164     @Test
165     public void whenFileIsExistsButJsonIsIncorrect() throws IOException, DatafileTaskException {
166
167         // When
168         doReturn(getIncorrectJson()).when(appConfigUnderTest).createInputStream(any());
169         appConfigUnderTest.loadConfigurationFromFile();
170
171         // Then
172         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
173         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
174         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
175             .hasMessageContaining(CHANGE_IDENTIFIER);
176         Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration());
177     }
178
179     @Test
180     public void whenTheConfigurationFits_ButRootElementIsNotAJsonObject() throws IOException, DatafileTaskException {
181
182         // When
183         doReturn(getCorrectJson()).when(appConfigUnderTest).createInputStream(any());
184         JsonElement jsonElement = mock(JsonElement.class);
185         when(jsonElement.isJsonObject()).thenReturn(false);
186         doReturn(jsonElement).when(appConfigUnderTest).getJsonElement(any(InputStream.class));
187         appConfigUnderTest.loadConfigurationFromFile();
188
189         // Then
190         verify(appConfigUnderTest, times(1)).loadConfigurationFromFile();
191         Assertions.assertNull(appConfigUnderTest.getDmaapConsumerConfiguration());
192         assertThatThrownBy(() -> appConfigUnderTest.getPublisherConfiguration(CHANGE_IDENTIFIER))
193             .hasMessageContaining(CHANGE_IDENTIFIER);
194         Assertions.assertNull(appConfigUnderTest.getCertificateConfiguration());
195     }
196
197     @Test
198     public void whenPeriodicConfigRefreshNoEnvironmentVariables() {
199         final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
200         Flux<AppConfig> task = appConfigUnderTest.createRefreshTask(context);
201
202         StepVerifier //
203             .create(task) //
204             .expectSubscription() //
205             .verifyComplete(); //
206
207         assertTrue(logAppender.list.toString().contains("CbsClientConfigurationException"));
208     }
209
210     @Test
211     public void whenPeriodicConfigRefreshNoConsul() {
212         doReturn(Mono.just(cbsClientConfiguration)).when(appConfigUnderTest).createCbsClientConfiguration();
213         doReturn(Mono.just(cbsClient)).when(appConfigUnderTest).createCbsClient(cbsClientConfiguration);
214         Flux<JsonObject> err = Flux.error(new IOException());
215         doReturn(err).when(cbsClient).updates(any(), any(), any());
216
217         final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(AppConfig.class);
218         Flux<AppConfig> task = appConfigUnderTest.createRefreshTask(context);
219
220         StepVerifier //
221             .create(task) //
222             .expectSubscription() //
223             .verifyComplete();
224
225         assertTrue(
226             logAppender.list.toString().contains("Could not refresh application configuration java.io.IOException"));
227     }
228
229     @Test
230     public void whenPeriodicConfigRefreshSuccess() throws JsonIOException, JsonSyntaxException, IOException {
231         doReturn(Mono.just(cbsClientConfiguration)).when(appConfigUnderTest).createCbsClientConfiguration();
232         doReturn(Mono.just(cbsClient)).when(appConfigUnderTest).createCbsClient(cbsClientConfiguration);
233
234         Flux<JsonObject> json = Flux.just(getJsonRootObject());
235         doReturn(json).when(cbsClient).updates(any(), any(), any());
236
237         Flux<AppConfig> task = appConfigUnderTest.createRefreshTask(context);
238
239         StepVerifier //
240             .create(task) //
241             .expectSubscription() //
242             .expectNext(appConfigUnderTest) //
243             .verifyComplete();
244
245         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
246     }
247
248     @Test
249     public void whenPeriodicConfigRefreshSuccess2() throws JsonIOException, JsonSyntaxException, IOException {
250         doReturn(Mono.just(cbsClientConfiguration)).when(appConfigUnderTest).createCbsClientConfiguration();
251         doReturn(Mono.just(cbsClient)).when(appConfigUnderTest).createCbsClient(cbsClientConfiguration);
252
253         Flux<JsonObject> json = Flux.just(getJsonRootObject());
254         Flux<JsonObject> err = Flux.error(new IOException()); // no config entry created by the
255         // dmaap plugin
256
257         doReturn(json, err).when(cbsClient).updates(any(), any(), any());
258
259         Flux<AppConfig> task = appConfigUnderTest.createRefreshTask(context);
260
261         StepVerifier //
262             .create(task) //
263             .expectSubscription() //
264             .expectNext(appConfigUnderTest) //
265             .verifyComplete();
266
267         Assertions.assertNotNull(appConfigUnderTest.getDmaapConsumerConfiguration());
268     }
269
270     private void checkCorrectConsumerConfiguration(ConsumerConfiguration consumerConfiguration) {
271         MessageRouterSubscribeRequest messageRouterSubscribeRequest =
272                 consumerConfiguration.getMessageRouterSubscribeRequest();
273         assertThat(messageRouterSubscribeRequest.consumerGroup()).isEqualTo("OpenDcae-c12");
274         assertThat(messageRouterSubscribeRequest.consumerId()).isEqualTo("C12");
275         assertThat(messageRouterSubscribeRequest.sourceDefinition().topicUrl())
276                 .isEqualTo("http://localhost:2222/events/unauthenticated.VES_NOTIFICATION_OUTPUT");
277         SecurityKeys securityKeys = consumerConfiguration.getMessageRouterSubscriberConfig().securityKeys();
278         assertThat(securityKeys.keyStore().path().toString()).isEqualTo("src/test/resources/cert.jks");
279         assertThat(securityKeys.trustStore().path().toString()).isEqualTo("src/test/resources/trust.jks");
280         assertThat(consumerConfiguration.getMessageRouterSubscriber()).isNotNull();
281     }
282
283     private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
284         JsonObject rootObject = JsonParser.parseReader(new InputStreamReader(getCorrectJson())).getAsJsonObject();
285         return rootObject;
286     }
287
288     private static InputStream getCorrectJson() throws IOException {
289         URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test.json");
290         String string = Resources.toString(url, Charsets.UTF_8);
291         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
292     }
293
294     private static InputStream getCorrectJsonTwoProducers() throws IOException {
295         URL url = CloudConfigParser.class.getClassLoader().getResource("datafile_endpoints_test_2producers.json");
296         String string = Resources.toString(url, Charsets.UTF_8);
297         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
298     }
299
300     private static InputStream getIncorrectJson() {
301         String string = "{" + //
302             "    \"configs\": {" + //
303             "        \"dmaap\": {"; //
304         return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
305     }
306 }