2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.drools.lifecycle;
23 import com.fasterxml.jackson.annotation.JsonIgnore;
24 import java.util.List;
26 import java.util.Properties;
27 import java.util.stream.Collectors;
29 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
30 import org.onap.policy.common.endpoints.event.comm.TopicSink;
31 import org.onap.policy.common.endpoints.event.comm.TopicSource;
32 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
33 import org.onap.policy.common.utils.coder.CoderException;
34 import org.onap.policy.drools.domain.models.controller.ControllerCustomSerialization;
35 import org.onap.policy.drools.domain.models.controller.ControllerEvent;
36 import org.onap.policy.drools.domain.models.controller.ControllerPolicy;
37 import org.onap.policy.drools.domain.models.controller.ControllerProperties;
38 import org.onap.policy.drools.domain.models.controller.ControllerSinkTopic;
39 import org.onap.policy.drools.domain.models.controller.ControllerSourceTopic;
40 import org.onap.policy.drools.properties.DroolsPropertyConstants;
41 import org.onap.policy.drools.system.PolicyController;
42 import org.onap.policy.drools.system.PolicyControllerConstants;
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class PolicyTypeNativeDroolsController implements PolicyTypeController {
49 private static final Logger logger = LoggerFactory.getLogger(PolicyTypeNativeDroolsController.class);
52 protected final ToscaPolicyTypeIdentifier policyType;
56 protected final transient LifecycleFsm fsm;
58 public PolicyTypeNativeDroolsController(LifecycleFsm fsm, ToscaPolicyTypeIdentifier policyType) {
59 this.policyType = policyType;
64 public boolean deploy(ToscaPolicy policy) {
65 Properties controllerProps = new Properties();
66 ControllerPolicy controllerPolicy = toDomainPolicy(policy);
67 if (controllerPolicy == null) {
71 ControllerProperties controllerConfig = controllerPolicy.getProperties();
74 configControllerName(controllerConfig, controllerProps)
75 && configControllerSources(controllerConfig, controllerProps)
76 && configControllerSinks(controllerConfig, controllerProps)
77 && configControllerCustom(controllerConfig, controllerProps);
83 PolicyController controller;
86 PolicyControllerConstants.getFactory().build(
87 controllerConfig.getControllerName(), controllerProps);
88 } catch (RuntimeException e) {
89 logger.warn("failed deploy (cannot create controller) for policy: {}", policy);
93 return controller != null;
97 public boolean undeploy(ToscaPolicy policy) {
99 ControllerPolicy nativePolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class);
100 PolicyControllerConstants.getFactory()
101 .destroy(nativePolicy.getProperties().getControllerName());
103 } catch (RuntimeException | CoderException e) {
104 logger.warn("failed undeploy of policy: {}", policy);
109 private ControllerPolicy toDomainPolicy(ToscaPolicy policy) {
110 ControllerPolicy nativePolicy = null;
112 nativePolicy = fsm.getDomainMaker().convertTo(policy, ControllerPolicy.class);
113 ControllerProperties config = nativePolicy.getProperties();
115 /* check for duplicates */
117 if (isDups(sourceTopics(config.getSourceTopics()))
118 || isDups(sinkTopics(config.getSinkTopics()))) {
119 logger.warn("there are duplicated topics in policy {}", policy);
123 /* check for non-existance of the controller - throws IAE if there's not */
125 PolicyControllerConstants.getFactory().get(nativePolicy.getProperties().getControllerName());
127 } catch (CoderException e) {
128 logger.warn("failed deploy of policy (invalid): {}", policy);
130 } catch (IllegalArgumentException e) {
132 logger.trace("proceeding with the deploy of native controller policy: {}", policy);
138 private boolean configControllerName(ControllerProperties controllerConfig, Properties controllerProps) {
140 .setProperty(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, controllerConfig.getControllerName());
144 private boolean configControllerSources(ControllerProperties controllerConfig, Properties controllerProps) {
145 for (ControllerSourceTopic configSourceTopic : controllerConfig.getSourceTopics()) {
146 List<TopicSource> sources =
147 TopicEndpointManager.getManager().getTopicSources(List.of(configSourceTopic.getTopicName()));
148 if (sources.size() != 1) {
149 logger.warn("Topic {} is not present or ambigous {}", configSourceTopic.getTopicName(), sources);
153 configSourceTopic(sources.get(0), configSourceTopic, controllerProps);
158 private void configSourceTopic(TopicSource topic, ControllerSourceTopic configTopic, Properties controllerProps) {
159 String configCommPrefix = topic.getTopicCommInfrastructure().name().toLowerCase() + ".source";
160 configTopic(configCommPrefix, topic.getTopic(), configTopic.getEvents(), controllerProps);
163 private boolean configControllerSinks(ControllerProperties controllerConfig, Properties controllerProps) {
164 for (ControllerSinkTopic configSinkTopic : controllerConfig.getSinkTopics()) {
165 List<TopicSink> sinks =
166 TopicEndpointManager.getManager().getTopicSinks(List.of(configSinkTopic.getTopicName()));
167 if (sinks.size() != 1) {
168 logger.warn("Topic {} is not present or ambigous {}", configSinkTopic.getTopicName(), sinks);
172 configSinkTopic(sinks.get(0), configSinkTopic, controllerProps);
177 private void configSinkTopic(TopicSink topic, ControllerSinkTopic configTopic, Properties controllerProps) {
178 String configCommPrefix = topic.getTopicCommInfrastructure().name().toLowerCase() + ".sink";
179 configTopic(configCommPrefix, topic.getTopic(), configTopic.getEvents(), controllerProps);
182 private void configTopic(
183 String configCommPrefix, String topicName, List<ControllerEvent> events, Properties controllerProps) {
184 String configTopicPrefix = configCommPrefix + "." + topicName;
185 configTopics(configCommPrefix, topicName, controllerProps);
186 for (ControllerEvent configEvent : events) {
187 configEvent(configTopicPrefix, configEvent, controllerProps);
191 private void configTopics(String propPrefix, String topicName, Properties controllerProps) {
192 String topicsPropKey = propPrefix + ".topics";
193 configTopicItemList(topicsPropKey, topicName, controllerProps);
196 private void configEvent(String propPrefix, ControllerEvent configEvent, Properties controllerProps) {
197 String eventPropPrefix = propPrefix + ".events";
198 controllerProps.setProperty(eventPropPrefix, configEvent.getEventClass());
199 if (configEvent.getEventFilter() != null) {
200 controllerProps.setProperty(
201 eventPropPrefix + "." + configEvent.getEventClass() + ".filter", configEvent.getEventFilter());
203 if (configEvent.getCustomSerialization() != null) {
204 configSerialization(eventPropPrefix, configEvent.getCustomSerialization(), controllerProps);
206 configTopicItemList(eventPropPrefix, configEvent.getEventClass(), controllerProps);
209 private void configTopicItemList(String itemPrefix, String item, Properties controllerProps) {
210 if (controllerProps.getProperty(itemPrefix) == null) {
211 controllerProps.setProperty(itemPrefix, item);
213 controllerProps.setProperty(itemPrefix, "," + item);
217 private void configSerialization(
218 String propPrefix, ControllerCustomSerialization configCustom, Properties controllerProps) {
219 String customPropPrefix = propPrefix + ".custom.gson";
220 controllerProps.setProperty(
221 customPropPrefix, configCustom.getCustomSerializerClass() + "," + configCustom.getJsonParser());
224 private boolean configControllerCustom(ControllerProperties controllerConfig, Properties controllerProps) {
225 Map<String, String> configCustom = controllerConfig.getCustomConfig();
226 if (configCustom == null || configCustom.isEmpty()) {
230 controllerProps.putAll(configCustom);
234 private <T> boolean isDups(List<T> items) {
235 return items.size() != items.stream().distinct().count();
238 private List<String> sourceTopics(List<ControllerSourceTopic> sourceTopics) {
239 return sourceTopics.stream()
240 .map(ControllerSourceTopic::getTopicName)
241 .collect(Collectors.toList());
244 private List<String> sinkTopics(List<ControllerSinkTopic> sourceTopics) {
245 return sourceTopics.stream()
246 .map(ControllerSinkTopic::getTopicName)
247 .collect(Collectors.toList());