Release 1.7.3 DCAEGEN2 VESCollector container
[dcaegen2/collectors/ves.git] / src / main / java / org / onap / dcae / controller / ConfigLoader.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.onap.dcaegen2.collectors.ves
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2018 Nokia. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.dcae.controller;
22
23 import static org.onap.dcae.common.publishing.DMaaPConfigurationParser.parseToDomainMapping;
24 import static org.onap.dcae.controller.ConfigParsing.getDMaaPConfig;
25 import static org.onap.dcae.controller.ConfigParsing.getProperties;
26 import static org.onap.dcae.controller.EnvPropertiesReader.readEnvProps;
27
28 import io.vavr.Function0;
29 import io.vavr.Function1;
30 import io.vavr.collection.HashMap;
31 import io.vavr.collection.Map;
32 import io.vavr.control.Try;
33 import java.nio.file.Path;
34 import java.util.function.Consumer;
35 import org.json.JSONObject;
36 import org.onap.dcae.VesApplication;
37 import org.onap.dcae.common.publishing.PublisherConfig;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class ConfigLoader {
42
43     private static final String SKIP_MSG = "Skipping dynamic configuration update";
44     private static Logger log = LoggerFactory.getLogger(ConfigLoader.class);
45     private final Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer;
46     private final ConfigFilesFacade configFilesFacade;
47     private final Function1<EnvProps, Try<JSONObject>> configurationSource;
48     private final Function0<Map<String, String>> envVariablesSupplier;
49     private boolean toRestart = false;
50
51     ConfigLoader(Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer,
52         ConfigFilesFacade configFilesFacade,
53         Function1<EnvProps, Try<JSONObject>> configurationSource,
54         Function0<Map<String, String>> envVariablesSupplier) {
55         this.eventPublisherReconfigurer = eventPublisherReconfigurer;
56         this.configFilesFacade = configFilesFacade;
57         this.configurationSource = configurationSource;
58         this.envVariablesSupplier = envVariablesSupplier;
59     }
60
61     public static ConfigLoader create(
62         Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer,
63         Path dMaaPConfigFile, Path propertiesConfigFile) {
64         return new ConfigLoader(eventPublisherReconfigurer,
65             new ConfigFilesFacade(dMaaPConfigFile, propertiesConfigFile),
66             ConfigSource::getAppConfig,
67             () -> HashMap.ofAll(System.getenv()));
68     }
69
70     public void updateConfig() {
71         log.info("Trying to dynamically update config from Config Binding Service");
72         readEnvProps(envVariablesSupplier.get())
73             .onEmpty(() -> log.warn(SKIP_MSG)).forEach(this::updateConfig);
74     }
75
76     private void updateConfig(EnvProps props) {
77         configurationSource.apply(props)
78             .onFailure(logSkip())
79             .onSuccess(newConf -> {
80                         updateConfigurationProperties(newConf);
81                         updateDMaaPProperties(newConf);
82                         reloadApplication();
83                 }
84             );
85     }
86
87     private void reloadApplication() {
88         if(toRestart){
89             log.info("New app config - Application will be restarted");
90             VesApplication.restartApplication();
91         }
92     }
93
94     private void updateDMaaPProperties(JSONObject newConf) {
95         configFilesFacade.readDMaaPConfiguration()
96             .onFailure(logSkip())
97             .onSuccess(oldDMaaPConf -> getDMaaPConfig(newConf)
98                 .onEmpty(() -> log.warn(SKIP_MSG))
99                 .forEach(newDMaaPConf -> compareAndOverwriteDMaaPConfig(oldDMaaPConf, newDMaaPConf)));
100     }
101
102
103     private void updateConfigurationProperties(JSONObject newConf) {
104         configFilesFacade.readCollectorProperties()
105             .onFailure(logSkip())
106             .onSuccess(oldProps -> compareAndOverwritePropertiesConfig(newConf, oldProps));
107     }
108
109     private void compareAndOverwritePropertiesConfig(JSONObject newConf, Map<String, String> oldProps) {
110         Map<String, String> newProperties = getProperties(newConf);
111         Map<String, String> result = oldProps.filterKeys((s) ->  newProperties.keySet().contains(s));
112         if (!result.equals(newProperties)) {
113             configFilesFacade.writeProperties(newProperties)
114                 .onSuccess(__ -> {
115                     toRestart= true;
116                     log.info("New properties configuration written to file");
117                  })
118                 .onFailure(logSkip());
119         } else {
120             log.info("Collector properties from CBS are the same as currently used ones. " + SKIP_MSG);
121         }
122     }
123
124     private void compareAndOverwriteDMaaPConfig(JSONObject oldDMaaPConf, JSONObject newDMaaPConf) {
125         if (!oldDMaaPConf.toString().equals(newDMaaPConf.toString())) {
126             parseToDomainMapping(newDMaaPConf)
127                 .onFailure(exc -> log.error(SKIP_MSG, exc))
128                 .onSuccess(eventPublisherReconfigurer)
129                 .onSuccess(parsedConfig ->
130                     configFilesFacade.writeDMaaPConfiguration(newDMaaPConf)
131                         .onFailure(logSkip())
132                         .onSuccess(__ -> {
133                             toRestart= true;
134                             log.info("New dMaaP configuration written to file");
135                         }));
136         } else {
137             log.info("DMaaP config from CBS is the same as currently used one. " + SKIP_MSG);
138         }
139     }
140
141     private Consumer<Throwable> logSkip() {
142         return __ -> log.error(SKIP_MSG);
143     }
144 }