Write async instantiations request-summary to DB
[vid.git] / vid-automation / src / test / java / org / onap / vid / api / InstantiationTemplatesApiTest.java
1 package org.onap.vid.api;
2
3 import static java.util.Arrays.stream;
4 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
5 import static org.hamcrest.MatcherAssert.assertThat;
6 import static org.hamcrest.Matchers.arrayWithSize;
7 import static org.hamcrest.Matchers.greaterThan;
8 import static org.onap.vid.api.TestUtils.convertRequest;
9 import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset;
10
11 import com.fasterxml.jackson.databind.JsonNode;
12 import com.fasterxml.jackson.databind.node.ObjectNode;
13 import com.google.common.collect.ImmutableMap;
14 import java.io.IOException;
15 import java.util.Map.Entry;
16 import java.util.function.Predicate;
17 import java.util.stream.Collectors;
18 import java.util.stream.Stream;
19 import org.onap.sdc.ci.tests.datatypes.UserCredentials;
20 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
21 import org.onap.vid.model.mso.MsoResponseWrapper2;
22 import org.springframework.core.ParameterizedTypeReference;
23 import org.springframework.http.HttpEntity;
24 import org.springframework.http.HttpMethod;
25 import org.testng.annotations.AfterMethod;
26 import org.testng.annotations.BeforeMethod;
27 import org.testng.annotations.Test;
28 import vid.automation.test.Constants.Users;
29 import vid.automation.test.infra.FeatureTogglingTest;
30 import vid.automation.test.infra.Features;
31 import vid.automation.test.model.User;
32 import vid.automation.test.services.AsyncJobsService;
33 import vid.automation.test.services.SimulatorApi.RegistrationStrategy;
34
35 public class InstantiationTemplatesApiTest extends AsyncInstantiationBase {
36
37     /*
38     Testing the Template Topology API should be very thin, given the following
39     assumptions:
40
41       - Template topology API is relying on Retry's logic.
42
43       - The templates themselves are an actual representation of the initial
44         state in VID's backend. This is all the knowledge that used to create
45         a service in the first time. So if API is fed with same state, it already
46         should be able to reiterate another instance.
47
48
49     The tests below will verify that:
50
51       - A request resulting from Cypress test on "instantiation-templates.e2e.ts"
52         is accepted by API endpoint
53
54       - A valid "regular" (not from template) request, yields a template that a
55         Cypress is able to deploy.
56
57       These two tests are, technically,  cyclic.
58
59       Currently the only test below is shortcutting the both tests, by checking
60       that feeding a Cypress input yields a Template that is the same. This is
61       not perfect, but currently what we have.
62
63      */
64
65     @Override
66     public UserCredentials getUserCredentials() {
67         User user = usersService.getUser(Users.SILVIA_ROBBINS_TYLER_SILVIA);
68         return new UserCredentials(user.credentials.userId, user.credentials.password, Users.SILVIA_ROBBINS_TYLER_SILVIA, "", "");
69     }
70
71     @BeforeMethod
72     public void setUp() {
73         registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), RegistrationStrategy.CLEAR_THEN_SET);
74     }
75
76     @AfterMethod
77     protected void dropAllFromNameCounter() {
78         AsyncJobsService asyncJobsService = new AsyncJobsService();
79         asyncJobsService.muteAllAsyncJobs();
80         asyncJobsService.dropAllFromNameCounter();
81     }
82
83     protected String templateTopologyUri(String jobId) {
84         return uri.toASCIIString() + "/instantiationTemplates/templateTopology/" + jobId;
85     }
86
87     @Test
88     public void templateTopology_givenDeployFromCypressE2E_getTemplateTopologyDataIsEquivalent() throws IOException {
89         templateTopology_givenDeploy_templateTopologyIsEquivalentToBody(
90             fileAsJsonNode("asyncInstantiation/templates__instance_template.json"));
91     }
92
93     @Test
94     public void templateTopology_givenDeployFromEditedTemplateCypressE2E_getTemplateTopologyDataIsEquivalentToOriginalTemplate() throws IOException {
95         templateTopology_givenDeploy_templateTopologyIsEquivalent(
96             fileAsJsonNode("asyncInstantiation/templates__instance_from_template__set_without_modify1.json"),
97             fileAsJsonNode("asyncInstantiation/templates__instance_template.json"));
98     }
99
100     @Test
101     @FeatureTogglingTest(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)
102     public void templateTopology_givenDeploy_getServiceInfoHoldsRequestSummary() throws IOException {
103         ObjectNode request =
104             fileAsJsonNode(CREATE_BULK_OF_MACRO_REQUEST)
105                 .put("bulkSize", 1)
106                 .put("pause", false);
107
108         postAsyncInstanceRequest(request);
109
110         assertThat(fetchRequestSummary(request.at("/modelInfo/modelVersionId").asText()),
111             jsonEquals(ImmutableMap.of(
112                 "vnf", 1L,
113                 "vfModule", 2L,
114                 "volumeGroup", 1L
115             )));
116     }
117
118     private JsonNode fetchRequestSummary(String serviceModelId) {
119         return stream(restTemplate.getForObject(getTemplateInfoUrl(serviceModelId), JsonNode[].class))
120             .map(it -> it.at("/requestSummary"))
121             .findFirst()
122             .orElseGet(() -> {
123                 throw new AssertionError(getTemplateInfoUrl(serviceModelId) + " returned zero results");
124             });
125     }
126
127     private ObjectNode fileAsJsonNode(String fileName) throws IOException {
128         return objectMapper.readValue(
129             convertRequest(objectMapper, fileName),
130             ObjectNode.class);
131     }
132
133     public void templateTopology_givenDeploy_templateTopologyIsEquivalentToBody(JsonNode body) {
134         templateTopology_givenDeploy_templateTopologyIsEquivalent(body, body);
135     }
136
137     public void templateTopology_givenDeploy_templateTopologyIsEquivalent(JsonNode body, JsonNode expectedTemplateTopology) {
138         String uuid1 = postAsyncInstanceRequest(body);
139         JsonNode templateTopology1 = restTemplate.getForObject(templateTopologyUri(uuid1), JsonNode.class);
140
141         assertThat(cleanupTemplate(templateTopology1), jsonEquals(cleanupTemplate(expectedTemplateTopology)));
142     }
143
144     private JsonNode cleanupTemplate(JsonNode templateTopology) {
145         return Stream.of(templateTopology)
146             .map(this::removeTrackById)
147             .map(this::removeNullValues)
148             .findAny().get();
149     }
150
151     private JsonNode removeTrackById(JsonNode node) {
152         return removeAny(node, it -> it.getKey().equals("trackById"));
153     }
154
155     private JsonNode removeNullValues(JsonNode node) {
156         return removeAny(node, it -> it.getValue().isNull());
157     }
158
159     private JsonNode removeAny(JsonNode node, Predicate<Entry<String, JsonNode>> entryPredicate) {
160         if (node.isObject()) {
161             ((ObjectNode) node).remove(
162                 Streams.fromIterator(node.fields())
163                     .filter(entryPredicate)
164                     .map(Entry::getKey)
165                     .collect(Collectors.toList())
166             );
167
168             for (JsonNode child : node) {
169                 removeAny(child, entryPredicate);
170             }
171         }
172
173         return node;
174     }
175
176     private <T> String postAsyncInstanceRequest(T body) {
177         String[] jobsUuids = (String[]) restTemplate.exchange(
178             getCreateBulkUri(),
179             HttpMethod.POST,
180             new HttpEntity<>(body),
181             new ParameterizedTypeReference<MsoResponseWrapper2<String[]>>() {
182             })
183             .getBody().getEntity();
184
185         assertThat(jobsUuids, arrayWithSize(greaterThan(0)));
186         return jobsUuids[0];
187     }
188
189 }