d01e2b5a0c4903ee5db7ac7d3f5d54b24f4f49dc
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.drools.apps.controller.usecases.step;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatCode;
25 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
37
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.TreeMap;
42 import java.util.UUID;
43 import java.util.concurrent.BlockingQueue;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.ForkJoinPool;
46 import java.util.concurrent.LinkedBlockingQueue;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.onap.aai.domain.yang.CloudRegion;
52 import org.onap.aai.domain.yang.GenericVnf;
53 import org.onap.aai.domain.yang.ModelVer;
54 import org.onap.aai.domain.yang.ServiceInstance;
55 import org.onap.aai.domain.yang.Tenant;
56 import org.onap.policy.aai.AaiCqResponse;
57 import org.onap.policy.common.utils.coder.StandardCoderObject;
58 import org.onap.policy.controlloop.VirtualControlLoopEvent;
59 import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation;
60 import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation;
61 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
62 import org.onap.policy.controlloop.actorserviceprovider.Operation;
63 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
64 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
65 import org.onap.policy.controlloop.actorserviceprovider.Operator;
66 import org.onap.policy.controlloop.actorserviceprovider.TargetType;
67 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
68 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
69 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
70 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2;
71 import org.onap.policy.controlloop.eventmanager.StepContext;
72 import org.onap.policy.drools.apps.controller.usecases.UsecasesConstants;
73
74 public class Step2Test {
75     private static final UUID REQ_ID = UUID.randomUUID();
76     private static final String POLICY_ACTOR = "my-actor";
77     private static final String POLICY_OPERATION = "my-operation";
78     private static final String MY_TARGET = "my-target";
79     private static final String PAYLOAD_KEY = "payload-key";
80     private static final String PAYLOAD_VALUE = "payload-value";
81     private static final String NO_SLASH = "noslash";
82     private static final String ONE_SLASH = "/one";
83
84     @Mock
85     private Operator policyOperator;
86     @Mock
87     private Operation policyOperation;
88     @Mock
89     private Actor policyActor;
90     @Mock
91     private ActorService actors;
92     @Mock
93     private StepContext stepContext;
94     @Mock
95     private AaiCqResponse aaicq;
96
97     private CompletableFuture<OperationOutcome> future;
98     private Map<String, String> payload;
99     private VirtualControlLoopEvent event;
100     private ControlLoopEventContext context;
101     private BlockingQueue<OperationOutcome> starts;
102     private BlockingQueue<OperationOutcome> completions;
103     private ControlLoopOperationParams params;
104     private Step2 step;
105
106     /**
107      * Sets up.
108      */
109     @Before
110     public void setUp() {
111         MockitoAnnotations.initMocks(this);
112
113         future = new CompletableFuture<>();
114
115         // configure policy operation
116         when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
117         when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
118         when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
119         when(policyOperation.start()).thenReturn(future);
120
121         when(policyOperation.getPropertyNames()).thenReturn(List.of());
122
123         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(aaicq);
124
125         payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
126
127         event = new VirtualControlLoopEvent();
128         event.setRequestId(REQ_ID);
129         event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
130         event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
131
132         context = new ControlLoopEventContext(event);
133
134         starts = new LinkedBlockingQueue<>();
135         completions = new LinkedBlockingQueue<>();
136
137         Map<String, String> entityIds = new HashMap<>();
138
139         params = ControlLoopOperationParams.builder().actor(POLICY_ACTOR).actorService(actors)
140                         .completeCallback(completions::add).context(context).executor(ForkJoinPool.commonPool())
141                         .operation(POLICY_OPERATION).payload(new TreeMap<>(payload)).startCallback(starts::add)
142                         .targetType(TargetType.VM).targetEntityIds(entityIds).targetEntity(MY_TARGET)
143                         .build();
144
145         step = new Step2(stepContext, params, event);
146         step.init();
147     }
148
149     @Test
150     public void testConstructor() {
151         assertSame(stepContext, step.stepContext);
152         assertSame(event, step.event);
153         assertSame(actors, step.getParams().getActorService());
154     }
155
156     @Test
157     public void testConstructorStep2() {
158         step = new Step2(step, "actorB", "operationB");
159         assertSame(stepContext, step.stepContext);
160         assertSame(event, step.event);
161
162         assertEquals("actorB", step.getActorName());
163         assertEquals("operationB", step.getOperationName());
164         assertSame(actors, step.getParams().getActorService());
165     }
166
167     @Test
168     public void testAcceptsEvent() {
169         // it's a policy step, thus it accepts events
170         assertTrue(step.acceptsEvent());
171
172         step = new Step2(step, "actorB", "operationB");
173
174         // it's not a policy step, thus it does not accept events
175         assertFalse(step.acceptsEvent());
176     }
177
178     @Test
179     public void testSuccess() {
180         assertThatCode(() -> step.success(null)).doesNotThrowAnyException();
181     }
182
183     @Test
184     public void testGetPropertyNames() {
185         // empty property list
186         assertThat(step.getPropertyNames()).isEmpty();
187
188         // try with non-empty list
189         when(policyOperation.getPropertyNames()).thenReturn(List.of("propA", "propB"));
190         assertThat(step.getPropertyNames()).isEqualTo(List.of("propA", "propB"));
191     }
192
193     @Test
194     public void testSetProperties() {
195         CloudRegion cloudRegion = new CloudRegion();
196         when(aaicq.getDefaultCloudRegion()).thenReturn(cloudRegion);
197
198         Tenant tenant = new Tenant();
199         when(aaicq.getDefaultTenant()).thenReturn(tenant);
200
201         when(policyOperation.getPropertyNames()).thenReturn(
202                         List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT));
203
204         step.setProperties();
205
206         // should have been exactly two properties set
207         verify(policyOperation, times(2)).setProperty(any(), any());
208         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, cloudRegion);
209         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, tenant);
210     }
211
212     /**
213      * Tests setProperties() when the property is unknown.
214      */
215     @Test
216     public void testSetPropertiesUnknown() {
217         when(policyOperation.getPropertyNames()).thenReturn(List.of("unknown-property"));
218
219         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
220                         .withMessage("unknown property unknown-property needed by my-actor.my-operation");
221     }
222
223     @Test
224     public void testLoadCloudRegion_testGetCloudRegion() {
225         CloudRegion data = new CloudRegion();
226         when(aaicq.getDefaultCloudRegion()).thenReturn(data);
227         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION));
228
229         step.setProperties();
230         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
231     }
232
233     @Test
234     public void testLoadTenant_testGetTenant() {
235         Tenant data = new Tenant();
236         when(aaicq.getDefaultTenant()).thenReturn(data);
237         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_DEFAULT_TENANT));
238
239         step.setProperties();
240         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
241     }
242
243     @Test
244     public void testLoadPnf_testGetPnf() {
245         StandardCoderObject data = new StandardCoderObject();
246         when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
247         when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(data);
248         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_PNF));
249
250         step.setProperties();
251         verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
252     }
253
254     @Test
255     public void testLoadResourceVnf_testGetResourceVnf() {
256         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, "my-resource");
257         GenericVnf data = new GenericVnf();
258         when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(data);
259         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_RESOURCE_VNF));
260
261         step.setProperties();
262         verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
263
264         // missing resource ID
265         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
266         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
267                         .withMessageContaining("missing Target resource ID");
268
269         // missing target entity IDs
270         params = params.toBuilder().targetEntityIds(null).build();
271         step = new Step2(stepContext, params, event);
272         step.init();
273         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
274                         .withMessageContaining(Step2.TARGET_INFO_MSG);
275     }
276
277     @Test
278     public void testLoadService_testGetService() {
279         ServiceInstance data = new ServiceInstance();
280         when(aaicq.getServiceInstance()).thenReturn(data);
281         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE));
282
283         step.setProperties();
284         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
285     }
286
287     @Test
288     public void testLoadServiceModel_testGetServiceModel() {
289         ServiceInstance service = new ServiceInstance();
290         service.setModelVersionId("my-service-version");
291         when(aaicq.getServiceInstance()).thenReturn(service);
292
293         ModelVer data = new ModelVer();
294         when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(data);
295         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_SERVICE_MODEL));
296
297         step.setProperties();
298         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
299     }
300
301     @Test
302     public void testLoadVnf_testGetVnf() {
303         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
304         GenericVnf data = new GenericVnf();
305         when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(data);
306         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF));
307
308         step.setProperties();
309         verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
310
311         // missing model invariant ID
312         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
313         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
314                         .withMessageContaining("missing modelInvariantId");
315
316         // missing target
317         params = params.toBuilder().targetEntityIds(null).build();
318         step = new Step2(stepContext, params, event);
319         step.init();
320         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
321                         .withMessageContaining(Step2.TARGET_INFO_MSG);
322     }
323
324     @Test
325     public void testLoadVnfModel_testGetVnfModel() {
326         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "my-model-invariant");
327         GenericVnf vnf = new GenericVnf();
328         when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(vnf);
329
330         vnf.setModelVersionId("my-vnf-model-version-id");
331         ModelVer data = new ModelVer();
332         when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(data);
333         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VNF_MODEL));
334
335         step.setProperties();
336         verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
337     }
338
339     @Test
340     public void testLoadVserverLink_testGetVserverLink() {
341         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, "vserverB"));
342
343         StandardCoderObject tenant = mock(StandardCoderObject.class);
344         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(tenant);
345
346         when(tenant.getString("result-data", 0, "resource-link")).thenReturn("/aai/v7/some/link/bbb");
347
348         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.AAI_VSERVER_LINK));
349
350         step.setProperties();
351         verify(policyOperation).setProperty(OperationProperties.AAI_VSERVER_LINK, "/some/link/bbb");
352
353         // missing resource link
354         when(tenant.getString("result-data", 0, "resource-link")).thenReturn(null);
355         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
356                         .withMessageContaining("missing tenant data resource-link");
357
358         // missing tenant data
359         when(stepContext.getProperty(AaiGetTenantOperation.getKey("vserverB"))).thenReturn(null);
360         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
361                         .withMessageContaining("missing tenant data for");
362
363         // empty vserver name
364         event.setAai(Map.of(Step2.VSERVER_VSERVER_NAME, ""));
365         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
366                         .withMessageContaining("missing vserver.vserver-name");
367
368         // missing vserver name
369         event.setAai(Map.of());
370         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
371                         .withMessageContaining("missing vserver.vserver-name");
372     }
373
374     @Test
375     public void testLoadVfCount_testGetVfCount() {
376         params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, "vf-count-customization");
377         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, "vf-count-invariant");
378         params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, "vf-count-version");
379         when(aaicq.getVfModuleCount("vf-count-customization", "vf-count-invariant", "vf-count-version")).thenReturn(11);
380         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.DATA_VF_COUNT));
381
382         step.setProperties();
383         verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 11);
384
385         // missing model version id
386         params.getTargetEntityIds().put(Step2.TARGET_MODEL_VERSION_ID, null);
387         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
388                         .withMessageContaining("missing target modelVersionId");
389
390         // missing model invariant id
391         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
392         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
393                         .withMessageContaining("missing target modelInvariantId");
394
395         // missing model customization id
396         params.getTargetEntityIds().put(Step2.TARGET_MODEL_CUSTOMIZATION_ID, null);
397         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
398                         .withMessageContaining("missing target modelCustomizationId");
399
400         // missing target
401         params = params.toBuilder().targetEntityIds(null).build();
402         step = new Step2(stepContext, params, event);
403         step.init();
404         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
405                         .withMessageContaining(Step2.TARGET_INFO_MSG);
406
407         // get it from the step context
408         when(stepContext.contains(OperationProperties.DATA_VF_COUNT)).thenReturn(true);
409         when(stepContext.getProperty(OperationProperties.DATA_VF_COUNT)).thenReturn(22);
410         step.setProperties();
411         verify(policyOperation).setProperty(OperationProperties.DATA_VF_COUNT, 22);
412     }
413
414     @Test
415     public void testLoadEnrichment_testGetEnrichment() {
416         event.setAai(Map.of("bandwidth", "bandwidth-value"));
417         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.ENRICHMENT_BANDWIDTH));
418
419         step.setProperties();
420         verify(policyOperation).setProperty(OperationProperties.ENRICHMENT_BANDWIDTH, "bandwidth-value");
421
422         // missing enrichment data
423         event.setAai(Map.of());
424         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties());
425     }
426
427     @Test
428     public void testLoadAdditionalEventParams_testGetAdditionalEventParams() {
429         Map<String, String> data = Map.of("addA", "add-valueA", "addB", "add-valueB");
430         event.setAdditionalEventParams(data);
431         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_ADDITIONAL_PARAMS));
432
433         step.setProperties();
434         verify(policyOperation).setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, data);
435     }
436
437     @Test
438     public void testLoadEventPayload_testGetEventPayload() {
439         event.setPayload("some-event-payload");
440         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.EVENT_PAYLOAD));
441
442         step.setProperties();
443         verify(policyOperation).setProperty(OperationProperties.EVENT_PAYLOAD, "some-event-payload");
444     }
445
446     @Test
447     public void testLoadOptCdsGrpcAaiProperties() {
448         when(policyOperation.getPropertyNames()).thenReturn(List.of(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES));
449
450         step.setProperties();
451         verify(policyOperation, never()).setProperty(any(), anyString());
452     }
453
454     @Test
455     public void testLoadDefaultGenericVnf_testGetDefaultGenericVnf() {
456         GenericVnf data = new GenericVnf();
457         when(aaicq.getDefaultGenericVnf()).thenReturn(data);
458         when(policyOperation.getPropertyNames()).thenReturn(List.of(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF));
459
460         step.setProperties();
461         verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
462     }
463
464     @Test
465     public void testGetCustomQueryData() {
466         assertSame(aaicq, step.getCustomQueryData());
467
468         when(stepContext.getProperty(AaiCqResponse.CONTEXT_KEY)).thenReturn(null);
469
470         assertThatIllegalArgumentException().isThrownBy(() -> step.getCustomQueryData())
471                         .withMessage("missing custom query data for my-actor.my-operation");
472     }
473
474     @Test
475     public void testVerifyNotNull() {
476         assertThatCode(() -> step.verifyNotNull("verifyA", "verify-value-A")).doesNotThrowAnyException();
477
478         assertThatIllegalArgumentException().isThrownBy(() -> step.verifyNotNull("verifyB", null))
479                         .withMessage("missing verifyB for my-actor.my-operation");
480     }
481
482     @Test
483     public void testStripPrefix() {
484         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 0));
485         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 1));
486         assertEquals(NO_SLASH, Step2.stripPrefix(NO_SLASH, 2));
487
488         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 1));
489         assertEquals(ONE_SLASH, Step2.stripPrefix(ONE_SLASH, 2));
490
491         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 2));
492         assertEquals("/slashes", Step2.stripPrefix("/two/slashes", 3));
493
494         assertEquals("/and/more", Step2.stripPrefix("/three/slashes/and/more", 3));
495
496         assertEquals("/and/more", Step2.stripPrefix("prefix/three/slashes/and/more", 3));
497     }
498
499 }