2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
4 * Modifications Copyright (C) 2021 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 * ============LICENSE_END=========================================================
20 package org.onap.policy.drools.server.restful;
22 import com.worldturner.medeia.api.ValidationFailedException;
23 import io.swagger.annotations.Api;
24 import io.swagger.annotations.ApiOperation;
25 import io.swagger.annotations.ApiParam;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Properties;
29 import javax.ws.rs.Consumes;
30 import javax.ws.rs.DELETE;
31 import javax.ws.rs.GET;
32 import javax.ws.rs.POST;
33 import javax.ws.rs.PUT;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.PathParam;
36 import javax.ws.rs.Produces;
37 import javax.ws.rs.core.MediaType;
38 import javax.ws.rs.core.Response;
39 import org.onap.policy.common.endpoints.event.comm.TopicSink;
40 import org.onap.policy.common.endpoints.event.comm.TopicSource;
41 import org.onap.policy.common.endpoints.http.server.YamlMessageBodyHandler;
42 import org.onap.policy.common.utils.coder.CoderException;
43 import org.onap.policy.common.utils.coder.StandardCoder;
44 import org.onap.policy.drools.lifecycle.LifecycleFeature;
45 import org.onap.policy.drools.lifecycle.PolicyTypeController;
46 import org.onap.policy.models.pdp.concepts.PdpStateChange;
47 import org.onap.policy.models.pdp.concepts.PdpStatistics;
48 import org.onap.policy.models.pdp.concepts.PdpUpdate;
49 import org.onap.policy.models.pdp.enums.PdpState;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 * REST Lifecycle Manager.
59 @Path("/policy/pdp/engine/lifecycle")
60 @Produces({MediaType.APPLICATION_JSON, YamlMessageBodyHandler.APPLICATION_YAML})
61 @Consumes({MediaType.APPLICATION_JSON, YamlMessageBodyHandler.APPLICATION_YAML})
63 public class RestLifecycleManager {
65 private static final Logger logger = LoggerFactory.getLogger(RestLifecycleManager.class);
67 private static final StandardCoder coder = new StandardCoder();
75 @ApiOperation(value = "Retrieves the Lifecycle group",
76 notes = "Lifecycle Group", response = String.class)
77 public Response group() {
78 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getGroup()).build();
86 @Path("group/{group}")
87 @ApiOperation(value = "Updates the Lifecycle group",
88 notes = "Lifecycle Group", response = String.class)
89 public Response updateGroup(
90 @ApiParam(value = "Group", required = true) @PathParam("group") String group) {
91 LifecycleFeature.getFsm().setGroup(group);
92 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getGroup()).build();
101 @ApiOperation(value = "Retrieves the Lifecycle subgroup",
102 notes = "Lifecycle Subgroup", response = String.class)
103 public Response subgroup() {
104 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSubGroup()).build();
112 @Path("subgroup/{subgroup}")
113 @ApiOperation(value = "Retrieves the Lifecycle subgroup",
114 notes = "Lifecycle Subgroup", response = String.class)
115 public Response subgroup(
116 @ApiParam(value = "Subgroup", required = true) @PathParam("subgroup") String subgroup) {
117 LifecycleFeature.getFsm().setSubGroup(subgroup);
118 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSubGroup()).build();
127 @ApiOperation(value = "Retrieves the Lifecycle properties",
128 notes = "Lifecycle Properties", response = Properties.class)
129 public Response properties() {
130 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getProperties()).build();
139 @ApiOperation(value = "Retrieves the Lifecycle state", notes = "Lifecycle State", response = PdpState.class)
140 public Response state() {
141 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().state()).build();
149 @Path("state/{state}")
150 @ApiOperation(value = "updates the Lifecycle state", notes = "Lifecycle State", response = Boolean.class)
151 public Response updateState(
152 @ApiParam(value = "state", required = true) @PathParam("state") String state) {
154 PdpStateChange change = new PdpStateChange();
155 change.setPdpGroup(LifecycleFeature.getFsm().getGroup());
156 change.setPdpSubgroup(LifecycleFeature.getFsm().getSubGroup());
157 change.setState(PdpState.valueOf(state));
158 change.setName(LifecycleFeature.getFsm().getName());
160 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().stateChange(change)).build();
168 @Path("topic/source")
169 @ApiOperation(value = "Retrieves the Lifecycle topic source",
170 notes = "Lifecycle Topic Source", response = TopicSource.class)
171 public Response source() {
172 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSource()).build();
181 @ApiOperation(value = "Retrieves the Lifecycle topic sink",
182 notes = "Lifecycle Topic Sink", response = TopicSink.class)
183 public Response sink() {
184 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getClient()).build();
188 * GET status interval.
192 @Path("status/interval")
193 @ApiOperation(value = "Retrieves the Lifecycle Status Timer Interval in seconds",
194 notes = "Lifecycle Status Timer Interval in seconds", response = Long.class)
195 public Response updateStatusTimer() {
196 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getStatusTimerSeconds()).build();
204 @Path("status/interval/{timeout}")
205 @ApiOperation(value = "Updates the Lifecycle Status Timer Interval in seconds",
206 notes = "Lifecycle Status Timer Interval in seconds", response = Long.class)
207 public Response statusTimer(
208 @ApiParam(value = "timeout", required = true) @PathParam("timeout") Long timeout) {
209 LifecycleFeature.getFsm().setStatusTimerSeconds(timeout);
210 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getStatusTimerSeconds()).build();
219 @ApiOperation(value = "List of supported policy types",
220 notes = "Lifecycle Policy Types", responseContainer = "List")
221 public Response policyTypes() {
222 return Response.status(Response.Status.OK)
223 .entity(LifecycleFeature.getFsm().getPolicyTypesMap().keySet())
232 @Path("policyTypes/{policyType}/{policyTypeVersion}")
233 @ApiOperation(value = "Entities associated with a policy type",
234 notes = "Lifecycle policy Types", response = PolicyTypeController.class)
235 public Response policyType(
236 @ApiParam(value = "Policy Type", required = true)
237 @PathParam("policyType") String policyType,
238 @ApiParam(value = "Policy Type Version", required = true)
239 @PathParam("policyTypeVersion") String policyTypeVersion) {
240 PolicyTypeController typeController =
241 LifecycleFeature.getFsm().getPolicyTypesMap()
242 .get(new ToscaConceptIdentifier(policyType, policyTypeVersion));
243 if (typeController == null) {
244 return Response.status(Response.Status.NOT_FOUND).build();
247 return Response.status(Response.Status.OK)
248 .entity(typeController)
258 @ApiOperation(value = "List of policies", responseContainer = "List")
259 public Response policies() {
260 return Response.status(Response.Status.OK)
261 .entity(LifecycleFeature.getFsm().getPoliciesMap().keySet())
272 @ApiOperation(value = "Deploy a policy", response = Boolean.class)
273 public Response deployTrackedPolicy(
274 @ApiParam(value = "Tosca Policy", required = true) String policy) {
276 ToscaPolicy toscaPolicy = getToscaPolicy(policy);
277 if (toscaPolicy == null) {
278 return Response.status(Response.Status.NOT_ACCEPTABLE).build();
281 PolicyTypeController typeController = getPolicyTypeController(toscaPolicy);
282 if (typeController == null) {
283 return Response.status(Response.Status.NOT_FOUND).build();
286 boolean updateResult = LifecycleFeature.getFsm().update(getDeployPolicyUpdate(List.of(toscaPolicy)));
287 return Response.status((updateResult ? Response.Status.OK : Response.Status.NOT_ACCEPTABLE))
288 .entity(updateResult)
297 @Path("policies/{policyName}/{policyVersion}")
298 @ApiOperation(value = "Retrieves a policy", response = ToscaPolicy.class)
299 public Response policy(
300 @ApiParam(value = "Policy Name", required = true) @PathParam("policyName") String policyName,
301 @ApiParam(value = "Policy Version", required = true) @PathParam("policyVersion") String policyVersion) {
306 LifecycleFeature.getFsm().getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion));
307 } catch (RuntimeException r) {
308 logger.debug("policy {}:{} has not been found", policyName, policyVersion, r);
309 return Response.status(Response.Status.NOT_FOUND).build();
312 if (policy == null) {
313 return Response.status(Response.Status.NOT_FOUND).build();
316 return Response.status(Response.Status.OK).entity(policy).build();
324 @Path("policies/{policyName}/{policyVersion}")
325 @ApiOperation(value = "Deletes a Lifecycle tracked policy", response = Boolean.class)
326 public Response undeployPolicy(
327 @ApiParam(value = "Policy", required = true) @PathParam("policyName") String policyName,
328 @ApiParam(value = "Policy Version", required = true) @PathParam("policyVersion") String policyVersion) {
333 LifecycleFeature.getFsm().getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion));
334 } catch (RuntimeException r) {
335 logger.debug("policy {}:{} has not been found", policyName, policyVersion, r);
336 return Response.status(Response.Status.NOT_FOUND).build();
339 if (policy == null) {
340 return Response.status(Response.Status.NOT_FOUND).build();
343 return Response.status(Response.Status.OK)
344 .entity(LifecycleFeature.getFsm().update(getUndeployPolicyUpdate(List.of(policy))))
349 * List of policies individual Operations supported.
353 @Path("policies/operations")
354 @ApiOperation(value = "Gets Policy Operations", responseContainer = "List")
355 public Response policiesOperations() {
356 return Response.status(Response.Status.OK).entity(List.of("deployment", "undeployment", "validation")).build();
360 * POST a deployment operation on a policy.
364 @Path("policies/operations/deployment")
365 @ApiOperation(value = "Deploys a policy", notes = "Deploys a policy", response = Boolean.class)
366 public Response deployOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) {
367 return deployUndeployOperation(policy, true);
371 * POST an undeployment operation on a policy.
375 @Path("policies/operations/undeployment")
376 @ApiOperation(value = "Undeploys a policy", response = Boolean.class)
377 public Response undeployOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) {
378 return deployUndeployOperation(policy, false);
382 * POST a policy for validation.
386 @Path("policies/operations/validation")
387 @ApiOperation(value = "Validates a policy", responseContainer = "List")
388 public Response validateOperation(@ApiParam(value = "Tosca Policy", required = true) String policy) {
389 ToscaPolicy toscaPolicy = getToscaPolicy(policy);
390 if (toscaPolicy == null) {
391 return Response.status(Response.Status.NOT_ACCEPTABLE).build();
395 LifecycleFeature.getFsm().getDomainMaker().conformance(toscaPolicy);
396 } catch (ValidationFailedException v) {
397 logger.trace("policy {} validation errors: {}", toscaPolicy, v.getMessage(), v);
398 return Response.status(Response.Status.NOT_ACCEPTABLE).entity(v.getFailures()).build();
401 return Response.status(Response.Status.OK).entity(Collections.emptyList()).build();
405 * Get current counts.
410 @ApiOperation(value = "Gets Policy Statistics", response = PdpStatistics.class)
411 public Response stats() {
412 return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().statisticsPayload()).build();
415 private Response deployUndeployOperation(String policy, boolean deploy) {
416 ToscaPolicy toscaPolicy = getToscaPolicy(policy);
417 if (toscaPolicy == null) {
418 return Response.status(Response.Status.NOT_ACCEPTABLE).build();
421 PolicyTypeController typeController = getPolicyTypeController(toscaPolicy);
422 if (typeController == null) {
423 return Response.status(Response.Status.NOT_FOUND).build();
426 return Response.status(Response.Status.OK)
427 .entity((deploy) ? typeController.deploy(toscaPolicy) : typeController.undeploy(toscaPolicy))
431 private ToscaPolicy getToscaPolicy(String policy) {
433 return coder.decode(policy, ToscaPolicy.class);
434 } catch (CoderException | RuntimeException e) {
439 private PolicyTypeController getPolicyTypeController(ToscaPolicy policy) {
440 return LifecycleFeature.getFsm().getPolicyTypesMap().get(policy.getTypeIdentifier());
443 private PdpUpdate getPolicyUpdate() {
444 PdpUpdate update = new PdpUpdate();
445 update.setName(LifecycleFeature.getFsm().getName());
446 update.setPdpGroup(LifecycleFeature.getFsm().getGroup());
447 update.setPdpSubgroup(LifecycleFeature.getFsm().getSubGroup());
451 private PdpUpdate getDeployPolicyUpdate(List<ToscaPolicy> policies) {
452 PdpUpdate update = getPolicyUpdate();
453 update.setPoliciesToBeDeployed(policies);
457 private PdpUpdate getUndeployPolicyUpdate(List<ToscaPolicy> policies) {
458 PdpUpdate update = getPolicyUpdate();
459 update.setPoliciesToBeUndeployed(LifecycleFeature.fsm.getPolicyIds(policies));