2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2021, 2024 Nordix Foundation.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.policy.drools.lifecycle;
24 import java.util.Collections;
25 import java.util.List;
27 import java.util.Properties;
28 import java.util.stream.Collectors;
29 import lombok.AllArgsConstructor;
31 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
32 import org.onap.policy.common.endpoints.event.comm.TopicSink;
33 import org.onap.policy.common.endpoints.event.comm.TopicSource;
34 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
35 import org.onap.policy.common.utils.coder.CoderException;
36 import org.onap.policy.drools.domain.models.controller.ControllerCustomSerialization;
37 import org.onap.policy.drools.domain.models.controller.ControllerEvent;
38 import org.onap.policy.drools.domain.models.controller.ControllerPolicy;
39 import org.onap.policy.drools.domain.models.controller.ControllerProperties;
40 import org.onap.policy.drools.domain.models.controller.ControllerSinkTopic;
41 import org.onap.policy.drools.domain.models.controller.ControllerSourceTopic;
42 import org.onap.policy.drools.properties.DroolsPropertyConstants;
43 import org.onap.policy.drools.system.PolicyController;
44 import org.onap.policy.drools.system.PolicyControllerConstants;
45 import org.onap.policy.drools.system.PolicyEngineConstants;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
52 public class PolicyTypeNativeDroolsController implements PolicyTypeController {
53 private static final Logger logger = LoggerFactory.getLogger(PolicyTypeNativeDroolsController.class);
56 protected final ToscaConceptIdentifier policyType;
59 protected final LifecycleFsm fsm;
62 public boolean deploy(ToscaPolicy policy) {
63 var controllerProps = new Properties();
64 var controllerPolicy = toDomainPolicy(policy);
65 if (controllerPolicy == null) {
69 ControllerProperties controllerConfig = controllerPolicy.getProperties();
71 configControllerName(controllerConfig, controllerProps);
74 configControllerSources(controllerConfig, controllerProps)
75 && configControllerSinks(controllerConfig, controllerProps)
76 && configControllerCustom(controllerConfig, controllerProps);
82 PolicyController controller;
85 PolicyEngineConstants.getManager()
86 .createPolicyController(controllerConfig.getControllerName(), controllerProps);
87 } catch (RuntimeException e) {
88 logger.warn("failed deploy (cannot create controller) for policy: {}", policy, e);
94 } catch (RuntimeException e) {
95 logger.warn("failed deploy (cannot start controller) for policy: {}", policy, e);
96 PolicyEngineConstants.getManager().removePolicyController(controller);
104 public boolean undeploy(ToscaPolicy policy) {
106 ControllerPolicy nativePolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class);
107 PolicyEngineConstants.getManager()
108 .removePolicyController(nativePolicy.getProperties().getControllerName());
110 } catch (RuntimeException | CoderException e) {
111 logger.warn("failed undeploy of policy: {}", policy);
116 private ControllerPolicy toDomainPolicy(ToscaPolicy policy) {
117 ControllerPolicy nativePolicy = null;
119 nativePolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class);
120 ControllerProperties config = nativePolicy.getProperties();
122 /* check for duplicates */
124 if (isDups(sourceTopics(config.getSourceTopics()))
125 || isDups(sinkTopics(config.getSinkTopics()))) {
126 logger.warn("there are duplicated topics in policy {}", policy);
130 /* check for non-existance of the controller - throws IAE if there's not */
132 PolicyControllerConstants.getFactory().get(nativePolicy.getProperties().getControllerName());
134 } catch (CoderException e) {
135 logger.warn("failed deploy of policy (invalid): {}", policy);
137 } catch (IllegalArgumentException e) {
139 logger.trace("proceeding with the deploy of native controller policy: {}", policy);
145 private void configControllerName(ControllerProperties controllerConfig, Properties controllerProps) {
147 .setProperty(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, controllerConfig.getControllerName());
150 private boolean configControllerSources(ControllerProperties controllerConfig, Properties controllerProps) {
151 if (controllerConfig.getSourceTopics() == null) {
155 for (ControllerSourceTopic configSourceTopic : controllerConfig.getSourceTopics()) {
156 List<TopicSource> sources =
157 TopicEndpointManager.getManager().getTopicSources(List.of(configSourceTopic.getTopicName()));
158 if (sources.size() != 1) {
159 logger.warn("Topic {} is not present or ambiguous {}", configSourceTopic.getTopicName(), sources);
163 configSourceTopic(sources.get(0), configSourceTopic, controllerProps);
168 private void configSourceTopic(TopicSource topic, ControllerSourceTopic configTopic, Properties controllerProps) {
169 String configCommPrefix = topic.getTopicCommInfrastructure().name().toLowerCase() + ".source";
170 configTopic(configCommPrefix, topic.getTopic(), configTopic.getEvents(), controllerProps);
173 private boolean configControllerSinks(ControllerProperties controllerConfig, Properties controllerProps) {
174 if (controllerConfig.getSinkTopics() == null) {
178 for (ControllerSinkTopic configSinkTopic : controllerConfig.getSinkTopics()) {
179 List<TopicSink> sinks =
180 TopicEndpointManager.getManager().getTopicSinks(List.of(configSinkTopic.getTopicName()));
181 if (sinks.size() != 1) {
182 logger.warn("Topic {} is not present or ambiguous {}", configSinkTopic.getTopicName(), sinks);
186 configSinkTopic(sinks.get(0), configSinkTopic, controllerProps);
191 private void configSinkTopic(TopicSink topic, ControllerSinkTopic configTopic, Properties controllerProps) {
192 String configCommPrefix = topic.getTopicCommInfrastructure().name().toLowerCase() + ".sink";
193 configTopic(configCommPrefix, topic.getTopic(), configTopic.getEvents(), controllerProps);
196 private void configTopic(
197 String configCommPrefix, String topicName, List<ControllerEvent> events, Properties controllerProps) {
198 String configTopicPrefix = configCommPrefix + ".topics." + topicName;
199 configTopics(configCommPrefix, topicName, controllerProps);
200 for (ControllerEvent configEvent : events) {
201 configEvent(configTopicPrefix, configEvent, controllerProps);
205 private void configTopics(String propPrefix, String topicName, Properties controllerProps) {
206 String topicsPropKey = propPrefix + ".topics";
207 configTopicItemList(topicsPropKey, topicName, controllerProps);
210 private void configEvent(String propPrefix, ControllerEvent configEvent, Properties controllerProps) {
211 String eventPropPrefix = propPrefix + ".events";
212 if (configEvent.getEventFilter() != null) {
213 controllerProps.setProperty(
214 eventPropPrefix + "." + configEvent.getEventClass() + ".filter", configEvent.getEventFilter());
216 if (configEvent.getCustomSerialization() != null) {
217 configSerialization(eventPropPrefix, configEvent.getCustomSerialization(), controllerProps);
219 configTopicItemList(eventPropPrefix, configEvent.getEventClass(), controllerProps);
222 private void configTopicItemList(String itemPrefix, String item, Properties controllerProps) {
223 String itemValue = controllerProps.getProperty(itemPrefix);
224 if (itemValue == null) {
225 controllerProps.setProperty(itemPrefix, item);
227 controllerProps.setProperty(itemPrefix, itemValue + "," + item);
231 private void configSerialization(
232 String propPrefix, ControllerCustomSerialization configCustom, Properties controllerProps) {
233 String customPropPrefix = propPrefix + ".custom.gson";
234 controllerProps.setProperty(
235 customPropPrefix, configCustom.getCustomSerializerClass() + "," + configCustom.getJsonParser());
238 private boolean configControllerCustom(ControllerProperties controllerConfig, Properties controllerProps) {
239 Map<String, String> configCustom = controllerConfig.getCustomConfig();
240 if (configCustom != null && !configCustom.isEmpty()) {
241 controllerProps.putAll(configCustom);
247 private <T> boolean isDups(List<T> items) {
248 return items.size() != items.stream().distinct().count();
251 private List<String> sourceTopics(List<ControllerSourceTopic> sourceTopics) {
252 if (sourceTopics == null) {
253 return Collections.emptyList();
256 return sourceTopics.stream()
257 .map(ControllerSourceTopic::getTopicName)
258 .collect(Collectors.toList());
261 private List<String> sinkTopics(List<ControllerSinkTopic> sinkTopics) {
262 if (sinkTopics == null) {
263 return Collections.emptyList();
266 return sinkTopics.stream()
267 .map(ControllerSinkTopic::getTopicName)
268 .collect(Collectors.toList());