94c73bf634dd8842de714146a6769ee36d1f14df
[sdnc/apps.git] /
1 /*
2  *  ============LICENSE_START===================================================
3  * Copyright (c) 2018 Amdocs
4  * ============================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ============LICENSE_END=====================================================
17  */
18
19 package org.onap.sdnc.apps.pomba.servicedecomposition.test;
20
21 import static com.github.tomakehurst.wiremock.client.WireMock.get;
22 import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
23 import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
24 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29
30 import com.github.tomakehurst.wiremock.junit.WireMockRule;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.util.Base64;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.ws.rs.core.HttpHeaders;
37 import javax.ws.rs.core.Response;
38 import javax.ws.rs.core.Response.Status;
39 import org.eclipse.jetty.util.security.Password;
40 import org.json.JSONArray;
41 import org.json.JSONObject;
42 import org.junit.Rule;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.onap.logging.ref.slf4j.ONAPLogConstants;
46 import org.onap.sdnc.apps.pomba.servicedecomposition.service.rs.RestService;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
49 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
50 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
51 import org.springframework.boot.test.context.SpringBootTest;
52 import org.springframework.test.context.TestPropertySource;
53 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
54 import org.springframework.test.context.web.WebAppConfiguration;
55
56 @RunWith(SpringJUnit4ClassRunner.class)
57 @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
58 @WebAppConfiguration
59 @SpringBootTest
60 @TestPropertySource(properties = {
61         "aai.httpProtocol=http",
62         "aai.host=localhost",
63         "aai.port=8081",
64         "basicAuth.username=admin",
65         "basicAuth.password=OBF:1u2a1toa1w8v1tok1u30"
66 })
67
68 public class ServiceDecompositionTest {
69
70     private static final String AUTH = "Basic " + Base64.getEncoder().encodeToString((
71             "admin:" + Password.deobfuscate("OBF:1u2a1toa1w8v1tok1u30")).getBytes());
72
73     // TODO missing code coverage for VNFC resources
74
75     @Rule
76     public WireMockRule aai = new WireMockRule(wireMockConfig().port(8081));
77
78     @Autowired
79     private RestService service;
80
81     /**
82      * Simulation of the firewall demo service, using json captured from real A&AI queries.
83      * The resource relationship looks something like.
84      * <pre>
85      * service instance
86      * +- generic-vnf 1
87      * |  +- vserver
88      * +- generic-vnf 2
89      *    +- network 1
90      *    +- network 2
91      * </pre>
92      */
93     @Test
94     public void testDemoFirewallService() throws Exception {
95         // setup A&AI responses
96         addResponse(
97                 "/aai/v13/nodes/service-instance/c6456519-6acf-4adb-997c-3c363dd4caaf",
98                 "junit/aai-service-instance.json");
99         addResponse(
100                 "/aai/v13/network/generic-vnfs/generic-vnf/6700c313-fbb7-4cf9-ac70-0293ec56df68?depth=2",
101                 "junit/aai-generic-vnf1.json");
102         addResponse(
103                 "/aai/v13/network/generic-vnfs/generic-vnf/8a9ddb25-2e79-449c-a40d-5011bac0da39?depth=2",
104                 "junit/aai-generic-vnf2.json");
105         addResponse(
106                 "/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant"
107                         + "/b49b830686654191bb1e952a74b014ad/vservers/vserver/b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a",
108                 "junit/aai-vserver.json");
109         addResponse(
110                 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951870",
111                 "junit/aai-l3-network1.json");
112         addResponse(
113                 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951872",
114                 "junit/aai-l3-network2.json");
115
116         final String serviceInstanceId = "c6456519-6acf-4adb-997c-3c363dd4caaf";
117         final String vnfId1 = "6700c313-fbb7-4cf9-ac70-0293ec56df68";
118         final String vnfId2 = "8a9ddb25-2e79-449c-a40d-5011bac0da39";
119         final String vserverId = "b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a";
120         final String networkId1 = "HNP1d77c-1094-41ec-b7f3-94bb30951870";
121         final String networkId2 = "HNP1d77c-1094-41ec-b7f3-94bb30951872";
122
123         HttpServletRequest httpRequest = new TestHttpServletRequest();
124         Response response = this.service.getContext(httpRequest, AUTH, "network-discovery-context-builder", null,
125                 serviceInstanceId);
126         assertEquals(200, response.getStatus());
127
128         JSONObject serviceInstance = new JSONObject((String)response.getEntity());
129
130         // verify two generic-vnfs added to service instance data
131         verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId1);
132         verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId2);
133
134         JSONArray vnfs = serviceInstance.getJSONArray("generic-vnfs");
135         for (int i = 0; i < vnfs.length(); i++) {
136             JSONObject vnf = vnfs.getJSONObject(i);
137             String vnfId = vnf.getString("vnf-id");
138             switch (vnfId) {
139                 case vnfId1:
140                     // verify vserver resource
141                     verifyResource(vnf, "vservers", "vserver-id", vserverId);
142                     break;
143                 case vnfId2:
144                     // verify network resources
145                     verifyResource(vnf, "l3-networks", "network-id", networkId1);
146                     verifyResource(vnf, "l3-networks", "network-id", networkId2);
147                     break;
148                 default:
149                     fail("Unexpected generic-vnf " + vnfId);
150             }
151         }
152     }
153
154     @Test
155     public void testNoAuthHeader() throws Exception {
156         String fromAppId = "junit";
157         String transactionId = null;
158         String serviceInstanceId = "aServiceInstanceId";
159         // no Authorization header
160         Response response = this.service.getContext(new TestHttpServletRequest(), null, fromAppId, transactionId,
161                 serviceInstanceId);
162         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
163         // should get WWW-Authenticate header in response
164         assertTrue(response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE).startsWith("Basic realm"));
165     }
166
167     @Test
168     public void testUnauthorized() throws Exception {
169         // bad credentials
170         String authorization = "Basic " + Base64.getEncoder().encodeToString("aaa:bbb".getBytes());
171         String fromAppId = "junit";
172         String transactionId = null;
173         String serviceInstanceId = "aServiceInstanceId";
174
175         Response response = this.service.getContext(new TestHttpServletRequest(), authorization, fromAppId,
176                 transactionId, serviceInstanceId);
177         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
178         // should not get WWW-Authenticate header in response
179         assertNull(response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE));
180     }
181
182     /** Fail if calling app name is missing. */
183     @Test
184     public void verifyFromAppId() throws Exception {
185         String fromAppId = null;
186         String transactionId = null;
187         String serviceInstanceId = "someValue";
188
189         Response response = this.service.getContext(new TestHttpServletRequest(), AUTH, fromAppId, transactionId,
190                 serviceInstanceId);
191         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
192         assertTrue(((String)response.getEntity()).contains(ONAPLogConstants.Headers.PARTNER_NAME));
193     }
194
195     /** Fail if service instance id is missing. */
196     @Test
197     public void verifyServiceInstanceId() throws Exception {
198         String fromAppId = "junit";
199         String transactionId = null;
200         String serviceInstanceId = null;
201
202         Response response = this.service.getContext(new TestHttpServletRequest(), AUTH, fromAppId, transactionId,
203                 serviceInstanceId);
204         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
205         assertTrue(((String)response.getEntity()).contains("service-instance-id"));
206     }
207
208     /** Unknown service-instance-id return HTTP 404. */
209     @Test
210     public void testInvalidServiceId() throws Exception {
211         aai.stubFor(get("/aai/v13/nodes/service-instance/noSuchServiceId").willReturn(notFound()));
212
213         Response response =
214                 this.service.getContext(new TestHttpServletRequest(), AUTH, "junit", null, "noSuchServiceId");
215
216         assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
217     }
218
219     private void verifyResource(JSONObject parent, String arrayName, String field, String value) {
220         JSONArray array = parent.getJSONArray(arrayName);
221         for (int i = 0; i < array.length(); i++) {
222             JSONObject item = array.getJSONObject(i);
223             if (value.equals(item.getString(field))) {
224                 return;
225             }
226         }
227         fail("Did not find " + field + "=" + value + " in " + arrayName + " array");
228     }
229
230     private void addResponse(String path, String classpathResource) throws IOException {
231         String payload = readFully(ClassLoader.getSystemResourceAsStream(classpathResource));
232         aai.stubFor(get(path).willReturn(okJson(payload)));
233     }
234
235     private String readFully(InputStream in) throws IOException {
236         char[] cbuf = new char[1024];
237         StringBuilder content = new StringBuilder();
238         try (InputStreamReader reader = new InputStreamReader(in, "UTF-8")) {
239             int count;
240             while ((count = reader.read(cbuf)) >= 0) {
241                 content.append(cbuf, 0, count);
242             }
243         }
244         return content.toString();
245     }
246 }