diff options
author | Jim Hahn <jrh3@att.com> | 2020-02-19 17:24:11 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2020-02-19 22:12:45 -0500 |
commit | 2e2eae531ad0d6e0e09a1cc4824fc5bb74432679 (patch) | |
tree | 78fa7c4f2aaf636fe13efd39faac66872a4df933 /models-interactions/model-actors/actor.guard/src/main | |
parent | 6226a42370795501971179de2fb2841a5de9ce6b (diff) |
Add Guard Actor
Issue-ID: POLICY-2350
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: Ib68c22a1154607563cb8a657b8101757a29b47ef
Diffstat (limited to 'models-interactions/model-actors/actor.guard/src/main')
3 files changed, 216 insertions, 0 deletions
diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java new file mode 100644 index 000000000..104c3830c --- /dev/null +++ b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardActorServiceProvider.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * SdncActorServiceProvider + * ================================================================================ + * Copyright (C) 2018-2019 Huawei Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.guard; + +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpActor; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; + +public class GuardActorServiceProvider extends HttpActor { + // actor name + public static final String NAME = "GUARD"; + + /** + * Constructs the object. + */ + public GuardActorServiceProvider() { + super(NAME); + + addOperator(HttpOperator.makeOperator(NAME, GuardOperation.NAME, + GuardOperation::new)); + } +} diff --git a/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java new file mode 100644 index 000000000..941838f00 --- /dev/null +++ b/models-interactions/model-actors/actor.guard/src/main/java/org/onap/policy/controlloop/actor/guard/GuardOperation.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop.actor.guard; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.Util; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperation; +import org.onap.policy.controlloop.actorserviceprovider.impl.HttpOperator; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Guard Operation. The outcome message is set to the guard response. If the guard is + * permitted or indeterminate, then the outcome is set to SUCCESS. + * <p/> + * The input to the request is taken from the payload, where properties are mapped to the + * field names in the {@link DecisionRequest} object. Properties whose names begin with + * "resource." are placed into the "resource" field of the {@link DecisionRequest}. The + * following will be provided, if not specified in the payload: + * <dl> + * <dt>action</dt> + * <dd>"guard"</dd> + * <dt>request ID</dt> + * <dd>generated</dd> + * </dl> + */ +public class GuardOperation extends HttpOperation<DecisionResponse> { + private static final Logger logger = LoggerFactory.getLogger(GuardOperation.class); + + // operation name + public static final String NAME = "Decision"; + + public static final String PERMIT = "Permit"; + public static final String DENY = "Deny"; + public static final String INDETERMINATE = "Indeterminate"; + + private static final String RESOURCE = "resource"; + + /** + * Prefix for properties in the payload that should be copied to the "resource" field + * of the request. + */ + public static final String RESOURCE_PREFIX = "resource."; + + + /** + * Constructs the object. + * + * @param params operation parameters + * @param operator operator that created this operation + */ + public GuardOperation(ControlLoopOperationParams params, HttpOperator operator) { + super(params, operator, DecisionResponse.class); + } + + @Override + protected CompletableFuture<OperationOutcome> startOperationAsync(int attempt, OperationOutcome outcome) { + + DecisionRequest request = Util.translate(getName(), makeRequest(), DecisionRequest.class); + + Entity<DecisionRequest> entity = Entity.entity(request, MediaType.APPLICATION_JSON); + + Map<String, Object> headers = makeHeaders(); + + headers.put("Accept", MediaType.APPLICATION_JSON); + String url = makeUrl(); + + logMessage(EventType.OUT, CommInfrastructure.REST, url, request); + + // @formatter:off + return handleResponse(outcome, url, + callback -> getOperator().getClient().post(callback, makePath(), entity, headers)); + // @formatter:on + } + + /** + * Makes a request from the payload. + * + * @return a new request map + */ + protected Map<String, Object> makeRequest() { + if (params.getPayload() == null) { + throw new IllegalArgumentException("missing payload"); + } + + /* + * This code could be easily modified to allow the context and/or resource to be + * an encoded JSON string, that is decoded into a Map and stuffed into the + * appropriate field. + */ + + Map<String, Object> req = new LinkedHashMap<>(); + Map<String, Object> resource = new LinkedHashMap<>(); + + for (Entry<String, String> ent : params.getPayload().entrySet()) { + String key = ent.getKey(); + + if (key.startsWith(RESOURCE_PREFIX)) { + // it's a resource property - put into the resource map + key = key.substring(RESOURCE_PREFIX.length()); + resource.put(key, ent.getValue()); + + } else if (key.indexOf('.') < 0) { + // it's a normal property - put into the request map + req.put(key, ent.getValue()); + + } else { + logger.warn("{}: unused key {} in payload for {}", getFullName(), key, params.getRequestId()); + } + } + + req.putIfAbsent("action", "guard"); + req.computeIfAbsent("requestId", key -> UUID.randomUUID().toString()); + req.put(RESOURCE, resource); + + return req; + } + + @Override + protected CompletableFuture<OperationOutcome> postProcessResponse(OperationOutcome outcome, String url, + Response rawResponse, DecisionResponse response) { + + // determine the result + String status = response.getStatus(); + if (status == null) { + outcome.setResult(PolicyResult.FAILURE); + outcome.setMessage("response contains no status"); + return CompletableFuture.completedFuture(outcome); + } + + if (PERMIT.equalsIgnoreCase(status) || INDETERMINATE.equalsIgnoreCase(status)) { + outcome.setResult(PolicyResult.SUCCESS); + } else { + outcome.setResult(PolicyResult.FAILURE); + } + + // set the message + outcome.setMessage(response.getStatus()); + + return CompletableFuture.completedFuture(outcome); + } +} diff --git a/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor new file mode 100644 index 000000000..dd4368504 --- /dev/null +++ b/models-interactions/model-actors/actor.guard/src/main/resources/META-INF/services/org.onap.policy.controlloop.actorServiceProvider.spi.Actor @@ -0,0 +1 @@ +org.onap.policy.controlloop.actor.guard.GuardActorServiceProvider |