Federation 3.2.0 - Model Data api
[federation.git] / gateway / src / test / java / org / acumos / federation / gateway / FederationControllerTest.java
1 /*-
2  * ===============LICENSE_START=======================================================
3  * Acumos
4  * ===================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
6  * ===================================================================================
7  * This Acumos software file is distributed by AT&T and Tech Mahindra
8  * under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * This file 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 package org.acumos.federation.gateway;
21
22 import java.io.InputStream;
23
24 import javax.servlet.http.HttpServletResponse;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.fail;
30 import org.junit.Test;
31 import org.junit.Before;
32 import org.junit.runner.RunWith;
33
34 import static org.mockito.Mockito.when;
35 import static org.mockito.Mockito.any;
36
37
38 import org.springframework.beans.factory.annotation.Autowired;
39 import org.springframework.boot.web.server.LocalServerPort;
40 import org.springframework.boot.test.context.SpringBootTest;
41 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
42 import org.springframework.boot.test.mock.mockito.MockBean;
43 import org.springframework.core.ParameterizedTypeReference;
44 import org.springframework.http.HttpMethod;
45 import org.springframework.test.context.junit4.SpringRunner;
46 import org.springframework.test.context.ContextConfiguration;
47 import org.springframework.web.client.HttpClientErrorException.Conflict;
48 import org.springframework.web.client.HttpClientErrorException.Forbidden;
49 import org.springframework.web.client.HttpClientErrorException.NotFound;
50 import org.springframework.web.client.HttpServerErrorException.InternalServerError;
51
52 import org.acumos.cds.client.ICommonDataServiceRestClient;
53 import org.acumos.cds.client.CommonDataServiceRestClientImpl;
54
55 import org.acumos.federation.client.FederationClient;
56 import org.acumos.federation.client.GatewayClient;
57 import org.acumos.federation.client.ClientBase;
58 import org.acumos.federation.client.config.ClientConfig;
59 import org.acumos.federation.client.config.BasicAuthConfig;
60 import org.acumos.federation.client.config.TlsConfig;
61 import org.acumos.federation.client.data.JsonResponse;
62 import org.acumos.federation.client.data.ModelData;
63
64 import org.acumos.federation.client.test.ClientMocking;
65 import org.apache.http.entity.ContentType;
66 import static org.acumos.federation.client.test.ClientMocking.getConfig;
67 import static org.acumos.federation.client.test.ClientMocking.xq;
68
69 @RunWith(SpringRunner.class)
70 @ContextConfiguration(classes=FederationServer.class)
71 @SpringBootTest(
72     classes = Application.class,
73     webEnvironment = WebEnvironment.RANDOM_PORT,
74     properties = {
75         "spring.main.allow-bean-definition-overriding=true",
76         "federation.ssl.key-store=classpath:acumosa.pkcs12",
77         "federation.ssl.key-store-password=acumosa",
78         "federation.ssl.key-store-type=PKCS12",
79         "federation.ssl.trust-store=classpath:acumosTrustStore.jks",
80         "federation.ssl.trust-store-password=acumos",
81         "federation.address=localhost",
82         "federation.server.port=0",
83         "federation.registration-enabled=true",
84         "cdms.client.url=http://dummy.org:999",
85         "cdms.client.username=dummyuser",
86         "cdms.client.password=dummypass",
87         "nexus.url=http://dummy.org:1234",
88         "logstash.url=http://logstash:2345",
89     }
90 )
91 public class FederationControllerTest {
92         @LocalServerPort
93         private int port;
94
95         @Autowired
96         private ServiceConfig cdmsConfig;
97
98         @Autowired
99         private NexusConfig nexusConfig;
100
101         @Autowired
102         private ServiceConfig logstashConfig;
103
104         @Autowired
105         private PeerService peerService;
106
107         @MockBean
108         private Clients clients;
109
110         private SimulatedDockerClient docker;
111
112         static ClientConfig anonConfig() {
113                 ClientConfig ret = getConfig("bogus");
114                 ret.getSsl().setKeyStore(null);
115                 ret.setCreds(null);
116                 return ret;
117         }
118
119         private static class RawAnonClient extends ClientBase {
120                 public RawAnonClient(String url) throws Exception {
121                         super(url, anonConfig(), null, null);
122                 }
123
124                 public byte[] get(String uri) {
125                         return handle(uri, HttpMethod.GET, new ParameterizedTypeReference<byte[]>(){});
126                 }
127         }
128
129         @Before
130         public void init() throws Exception {
131                 String url = cdmsConfig.getUrl();
132                 ClientConfig ccc = new ClientConfig();
133                 ccc.setCreds(cdmsConfig);
134                 ICommonDataServiceRestClient cdsClient = CommonDataServiceRestClientImpl.getInstance(url, ClientBase.buildRestTemplate(url, ccc, null, null));
135
136                 (new ClientMocking())
137                     .on("GET /peer/search?self=true&subjectName=gateway.acumosa.org&_j=a&page=0&size=100", xq("{ 'content': [ {'peerId': '1', 'subjectName': 'gateway.acumosa.org', 'statusCode': 'AC', 'self': true, 'local': true } ], 'last': true, 'number': 0, 'size': 100, 'numberOfElements': 1 }"))
138                     .on("GET /peer/search?subjectName=gateway.acumosa.org&_j=a&page=0&size=100", xq("{ 'content': [ {'peerId': '1', 'subjectName': 'gateway.acumosa.org', 'statusCode': 'AC', 'self': true } ], 'last': true, 'number': 0, 'size': 100, 'numberOfElements': 1 }"))
139                     .on("GET /peer/search?subjectName=gateway.acumosb.org&_j=a&page=0&size=100", xq("{ 'content': [ {'peerId': '2', 'subjectName': 'gateway.acumosb.org', 'statusCode': 'XX', 'self': false } ], 'last': true, 'number': 0, 'size': 100, 'numberOfElements': 1 }"))
140                     .on("GET /peer/search?self=true&subjectName=Bad=?#/.CN%Value&_j=a&page=0&size=100", xq("{}"))
141                     .on("GET /peer/2", xq("{'peerId': '2', 'subjectName': 'gateway.acumosb.org', 'statusCode': 'RQ', 'self': false }"))
142                     .on("PUT /peer/2", "")
143                     .on("GET /peer/search?subjectName=gateway.acumosc.org&_j=a&page=0&size=100", xq("{ 'content': [ ], 'last': true, 'number': 0, 'size': 100, 'numberOfElements': 0 }"))
144                     .on("POST /peer", xq("{}"))
145                     .on("GET /catalog/search?accessTypeCode=PB&_j=a&page=0&size=100", xq("{ 'content': [ { 'catalogId': '1' }, { 'catalogId': '2' } ], 'last': true, 'number': 2, 'size': 100, 'numberOfElements': 2 }"))
146                     .on("GET /access/peer/1/catalog", xq("[ '2', '7', '8' ]"))
147                     .on("GET /peer?page=0&size=100", xq("{ 'content': [ { 'peerId': '1' }, { 'peerId': '2' } ], 'last': true, 'number': 2, 'size': 100, 'numberOfElements': 2 }"))
148                     .on("GET /catalog/1/solution/count", xq("{ 'count': 1 }"))
149                     .on("GET /catalog/2/solution/count", xq("{ 'count': 2 }"))
150                     .on("GET /catalog/7", xq("{ 'catalogId': '7' }"))
151                     .on("GET /catalog/7/solution/count", xq("{ 'count': 3 }"))
152                     .on("GET /catalog/8", "")
153                     .on("GET /peer/search?self=true&subjectName=No.Such.Peer&_j=a&page=0&size=100", xq("{ 'content': [], 'last': true, 'number': 0, 'size': 100, 'numberOfElements': 0 }"))
154                     .on("GET /access/peer/1/catalog/somecatid", xq("{ 'count': '1' }"))
155                     .on("GET /access/peer/1/catalog/badcatid", xq("{ 'count': '0' }"))
156                     .on("GET /catalog/solution?ctlg=somecatid&page=0&size=100", xq("{ 'content': [ { 'solutionId': 'somesolid' }, { 'solutionId': 'othersolid', 'origin': 'https://someoneelse.org:1234/solution/othersolid' } ], 'last': true, 'number': 2, 'size': 100, 'numberOfElements': 2 }"))
157                     .on("GET /access/peer/1/solution/somesolid", xq("{ 'count': '1' }"))
158                     .on("GET /access/peer/1/solution/badsolid", xq("{ 'count': '0' }"))
159                     .on("GET /access/peer/1/solution/norevssolid", xq("{ 'count': '1' }"))
160                     .on("GET /solution/somesolid", xq("{ 'solutionId': 'somesolid' }"))
161                     .on("GET /solution/norevssolid", xq("{ 'solutionId': 'norevssolid' }"))
162                     .on("GET /solution/somesolid/revision", xq("[ { 'solutionId': 'somesolid', 'revisionId': 'somerevid' }, { 'solutionId': 'somesolid', 'revisionId': 'otherrevid' } ]"))
163                     .on("GET /solution/norevssolid/revision", "[]")
164                     .on("GET /solution/somesolid/pic", "")
165                     .on("GET /solution/ignored/revision/somerevid", xq("{ 'solutionId': 'somesolid', 'revisionId': 'somerevid' }"))
166                     .on("GET /solution/ignored/revision/badrevid", xq("{ 'solutionId': 'badsolid', 'revisionId': 'badrevid' }"))
167                     .on("GET /solution/ignored/revision/norevid", "")
168                     .on("GET /revision/somerevid/artifact", xq("[ { 'artifactId': 'someartid' }, { 'artifactId': 'otherartid', 'uri': 'dockerregistry:997/a/b', 'artifactTypeCode': 'DI' }, { 'artifactId': 'nexusartid', 'uri': 'a/b/c.x' } ]"))
169                     .on("GET /revision/badrevid/artifact", xq("[ { 'artifactId': 'badartid' }, { 'artifactId': 'otherbadartid' } ]"))
170                     .on("GET /revision/somerevid/catalog/somecatid/descr", xq("{ 'revisionId': 'somerevid', 'catalogId': 'somecatid', 'description': 'Etc., etc., etc.' }"))
171                     .on("GET /revision/somerevid/catalog/somecatid/document", xq("[ { 'documentId': 'somedocid' }, { 'documentId': 'otherdocid' } ]"))
172                     .on("GET /artifact/someartid", xq("{ 'artifactId': 'someartid', 'uri': 'a/b/c/d' }"))
173                     .on("GET /artifact/dockerartid", xq("{ 'artifactId': 'someartid', 'uri': 'dockerregistry:1234/a/b:1.0', 'artifactTypeCode': 'DI' }"))
174                     .on("GET /document/somedocid", xq("{ 'documentId': 'somedocid', 'uri': 'd/c/b/a' }"))
175                     .on("GET /peer/1/sub", "[]")
176                     .on("GET /peer/2/sub", "[]")
177                     .on("GET /solution/ignored/revision/altrevid", xq("{ 'solutionId': 'somesolid', 'revisionId': 'altrevid' }"))
178                     .on("GET /revision/altrevid/artifact", xq("[ { 'artifactId': 'altart1', 'artifactTypeCode': 'DI', 'version': 'aa1ver', 'uri': 'host:999/xxx/stuff:aa1ver' }, { 'artifactId': 'altart2', 'artifactTypeCode': 'DI', 'version': 'aa2ver', 'uri': 'someimagename' }]"))
179                     .on("GET /revision/altrevid/catalog/somecatid/document", xq("[ { 'documentId': 'altdoc1', 'version': 'ad1ver', 'uri': 'somepath/ad1name/ua/ad1name-ua.ad1type' }, { 'documentId': 'altdoc2', 'version': 'ad2ver', 'uri': 'somepath/ad2name/ua/ad2name.ad2type' }]"))
180                     .applyTo(cdsClient);
181
182                 when(clients.getCDSClient()).thenReturn(cdsClient);
183
184                 ClientConfig ncc = new ClientConfig();
185                 ncc.setCreds(nexusConfig);
186                 NexusClient nexusClient = new NexusClient(nexusConfig.getUrl(), ncc);
187
188                 (new ClientMocking())
189                     .on("GET /a/b/c/d", "vwxyz")
190                     .on("GET /d/c/b/a", "wxyz")
191                     .applyTo(nexusClient);
192                 when(clients.getNexusClient()).thenReturn(nexusClient);
193
194                 docker = new SimulatedDockerClient();
195                 docker.setSaveResult("abcdefg".getBytes());
196                 when(clients.getDockerClient()).thenReturn(docker.getClient());
197
198                 initLogstashMock(clients);
199         }
200
201         public void initLogstashMock(Clients clients) throws Exception {
202
203                 String url = logstashConfig.getUrl();
204                 ClientConfig ccc = new ClientConfig();
205                 ccc.setCreds(logstashConfig);
206                 LogstashClient mockLogstashClient = new LogstashClient(url, ccc);
207
208                 (new ClientMocking())
209                     .on("POST /", "ok", ContentType.TEXT_PLAIN)
210                     .applyTo(mockLogstashClient);
211
212                 when(clients.getLogstashClient()).thenReturn(mockLogstashClient);
213
214         }
215
216         @Test
217         public void testConfig() throws Exception {
218
219                 FederationClient self = new FederationClient("https://localhost:" + port, getConfig("acumosa"));
220                 FederationClient known = new FederationClient("https://localhost:" + port, getConfig("acumosb"));
221                 FederationClient unknown = new FederationClient("https://localhost:" + port, getConfig("acumosc"));
222                 assertNotNull(unknown.register());
223                 try {
224                         self.register();
225                         fail();
226                 } catch (Conflict c) {
227                         // expected case
228                 }
229                 assertNotNull(known.unregister());
230                 assertNotNull(self.ping());
231                 assertEquals(2, self.getPeers().size());
232                 try {
233                         unknown.unregister();
234                         fail();
235                 } catch (Forbidden ux) {
236                         // expected case
237                 }
238                 try {
239                         known.ping();
240                         fail();
241                 } catch (Forbidden ux) {
242                         // expected case
243                 }
244                 assertEquals(3, self.getCatalogs().size());
245                 assertNull(peerService.getSelf("No.Such.Peer"));
246                 assertEquals(2, self.getSolutions("somecatid").size());
247                 try {
248                         self.getSolutions("badcatid");
249                         fail();
250                 } catch (NotFound nf) {
251                         // expected case
252                 }
253                 assertNotNull(self.getSolution("somesolid"));
254                 try {
255                         self.getSolution("badsolid");
256                         fail();
257                 } catch (NotFound nf) {
258                         // expected case
259                 }
260                 try {
261                         self.getSolution("norevssolid");
262                         fail();
263                 } catch (NotFound nf) {
264                         // expected case
265                 }
266                 assertEquals(2, self.getSolutionRevisions("somesolid").size());
267                 try {
268                         self.getSolutionRevisions("badsolid");
269                         fail();
270                 } catch (NotFound nf) {
271                         // expected case
272                 }
273                 try {
274                         self.getSolutionRevisions("norevssolid");
275                         fail();
276                 } catch (NotFound nf) {
277                         // expected case
278                 }
279                 assertNotNull(self.getSolutionRevision("somesolid", "somerevid", "somecatid"));
280                 try {
281                         self.getSolutionRevision("somesolid", "badrevid", "badcatid");
282                         fail();
283                 } catch (NotFound nf) {
284                         // expected case
285                 }
286                 try {
287                         self.getSolutionRevision("somesolid", "norevid", null);
288                         fail();
289                 } catch (NotFound nf) {
290                         // expected case
291                 }
292                 assertEquals(3, self.getArtifacts("somesolid", "somerevid").size());
293                 try {
294                         self.getArtifacts("somesolid", "badrevid");
295                         fail();
296                 } catch (NotFound nf) {
297                         // expected case
298                 }
299                 try {
300                         self.getArtifacts("somesolid", "norevid");
301                         fail();
302                 } catch (NotFound nf) {
303                         // expected case
304                 }
305                 byte[] buf = new byte[1000];
306                 try (InputStream is = self.getArtifactContent("someartid")) {
307                         assertEquals(5, is.read(buf));
308                 }
309                 try (InputStream is = self.getArtifactContent("dockerartid")) {
310                         assertEquals(7, is.read(buf));
311                 }
312                 docker.setDoPullTimeout(true);
313                 try {
314                         self.getArtifactContent("dockerartid");
315                         fail();
316                 } catch (InternalServerError ise) {
317                         // expected case
318                 }
319                 assertEquals(2, self.getDocuments("somerevid", "somecatid").size());
320                 try (InputStream is = self.getDocumentContent("somedocid")) {
321                         assertEquals(4, is.read(buf));
322                 }
323                 try {
324                         self.getDocuments("somerevid", "badcatid");
325                         fail();
326                 } catch (NotFound nf) {
327                         // expected case
328                 }
329                 assertNotNull(self.getDocuments("altrevid", "somecatid"));
330                 assertNotNull(self.getArtifacts("somesolid", "altrevid"));
331         }
332
333         @Test
334         public void testModelData() throws Exception {
335                 FederationClient self = new FederationClient("https://localhost:" + port, getConfig("acumosa"));
336
337                 ObjectMapper objectMapper = new ObjectMapper();
338                 ModelData payloadObjectNode =  objectMapper.readValue("{\"model\": { \"solutionId\": \"UUID\"}}", ModelData.class);
339                 try {
340                         self.receiveModelData(payloadObjectNode);
341                 } catch (Exception e) {
342                         System.err.println(e);
343                         fail("exception when sending model data not expected");
344                 }
345         }
346
347
348         @Test
349         public void testSwagger() throws Exception {
350                 RawAnonClient rac = new RawAnonClient("https://localhost:" + port);
351                 assertNotNull(rac);
352                 rac.get("/swagger-ui.html");
353                 rac.get("/v2/api-docs");
354         }
355 }