From a46c269e0972357c54378520a4bba531bf7bb12d Mon Sep 17 00:00:00 2001 From: "aravind.est" Date: Wed, 14 Feb 2024 14:26:41 +0000 Subject: [PATCH] Add support to upload deployment helm artifacts to chartmuseum HELM artifacts can be defined as part of the rApp package. These artifacts will be uploaded to the chartmuseum server as part of the rApp priming process. Issue-ID: NONRTRIC-975 Change-Id: Ia65e7756cc76763d25362ac1f5261785e7a65d18 Signed-off-by: aravind.est --- .../service/DeploymentArtifactsService.java | 78 +++++++++++ .../oransc/rappmanager/service/RappService.java | 8 +- .../service/DeploymentArtifactsServiceTest.java | 151 +++++++++++++++++++++ .../rappmanager/service/RappServiceTest.java | 16 +++ .../src/test/resources/invalid-rapp-package.csar | Bin 6924 -> 6759 bytes .../src/test/resources/valid-rapp-package.csar | Bin 23620 -> 23673 bytes .../rappmanager/models/csar/DeploymentItem.java | 40 ++++++ .../models/csar/DeploymentItemArtifactType.java | 26 ++++ .../models/csar/DeploymentItemTargetServer.java | 27 ++++ .../models/csar/RappCsarConfigurationHandler.java | 70 ++++++++-- .../csar/RappCsarConfigurationHandlerTest.java | 39 +++++- .../invalid-rapp-package-empty-asd-yaml.csar | Bin 0 -> 23233 bytes .../src/test/resources/valid-rapp-package.csar | Bin 23620 -> 23673 bytes .../rapp-all/Definitions/asd.yaml | 10 +- .../rapp-all/Definitions/asd_types.yaml | 43 +++--- 15 files changed, 471 insertions(+), 37 deletions(-) create mode 100755 rapp-manager-application/src/main/java/com/oransc/rappmanager/service/DeploymentArtifactsService.java create mode 100755 rapp-manager-application/src/test/java/com/oransc/rappmanager/service/DeploymentArtifactsServiceTest.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/DeploymentItem.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/DeploymentItemArtifactType.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/DeploymentItemTargetServer.java create mode 100755 rapp-manager-models/src/test/resources/invalid-rapp-package-empty-asd-yaml.csar diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/DeploymentArtifactsService.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/DeploymentArtifactsService.java new file mode 100755 index 0000000..aaafdb2 --- /dev/null +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/DeploymentArtifactsService.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.service; + +import com.oransc.rappmanager.models.csar.DeploymentItem; +import com.oransc.rappmanager.models.csar.DeploymentItemArtifactType; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.exception.RappHandlerException; +import com.oransc.rappmanager.models.rapp.Rapp; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@Service +@RequiredArgsConstructor +public class DeploymentArtifactsService { + + private final RestTemplate restTemplate; + private final RappCsarConfigurationHandler rappCsarConfigurationHandler; + + public boolean configureDeploymentArtifacts(Rapp rapp) { + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + return deploymentItems.stream().filter(deploymentItem -> deploymentItem.getArtifactType() + .equals(DeploymentItemArtifactType.HELMCHART)) + .allMatch(deploymentItem -> uploadHelmChart(rapp, deploymentItem)); + } + + boolean uploadHelmChart(Rapp rApp, DeploymentItem deploymentItem) throws RappHandlerException { + try { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); + HttpEntity requestHttpEntity = + new HttpEntity<>(rappCsarConfigurationHandler.getArtifactPayload(rApp, deploymentItem.getFile()), + httpHeaders); + ResponseEntity responseEntity = + restTemplate.exchange(deploymentItem.getTargetServerUri(), HttpMethod.POST, requestHttpEntity, + String.class); + if (responseEntity.getStatusCode().is2xxSuccessful()) { + return true; + } + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode().equals(HttpStatus.CONFLICT)) { + return true; + } + } catch (Exception e) { + throw new RappHandlerException(HttpStatus.BAD_REQUEST, + String.format("Unable to connect to the chartmuseum server %s to upload helm artifact %s", + deploymentItem.getTargetServerUri(), deploymentItem.getFile())); + } + return false; + } +} diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java index 8e71d50..23ab2d8 100755 --- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java @@ -44,13 +44,19 @@ public class RappService { private final List rappDeployers; private final RappInstanceStateMachine rappInstanceStateMachine; private final RappCacheService rappCacheService; + private final DeploymentArtifactsService deploymentArtifactsService; private static final String STATE_TRANSITION_NOT_PERMITTED = "State transition from %s to %s is not permitted."; public ResponseEntity primeRapp(Rapp rapp) { if (rapp.getState().equals(RappState.COMMISSIONED)) { rapp.setState(RappState.PRIMING); rapp.setReason(null); - if (rappDeployers.parallelStream().allMatch(rappDeployer -> rappDeployer.primeRapp(rapp))) { + //Configuring the deployment artifact needs to be done before starting the priming with other components + //If there are additional conditions needs to be checked before priming, This needs handled as part of pre-priming stage. + if (deploymentArtifactsService.configureDeploymentArtifacts(rapp) && rappDeployers.parallelStream() + .allMatch( + rappDeployer -> rappDeployer.primeRapp( + rapp))) { rapp.setState(RappState.PRIMED); return ResponseEntity.ok().build(); } diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/DeploymentArtifactsServiceTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/DeploymentArtifactsServiceTest.java new file mode 100755 index 0000000..4a3a08a --- /dev/null +++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/DeploymentArtifactsServiceTest.java @@ -0,0 +1,151 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withException; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withTooManyRequests; + +import com.oransc.rappmanager.models.csar.DeploymentItem; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.exception.RappHandlerException; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.sme.service.SmeLifecycleManager; +import java.io.IOException; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class DeploymentArtifactsServiceTest { + + @SpyBean + DeploymentArtifactsService deploymentArtifactsService; + @Autowired + RestTemplate restTemplate; + @Autowired + RappCsarConfigurationHandler rappCsarConfigurationHandler; + @MockBean + SmeLifecycleManager smeLifecycleManager; + + MockRestServiceServer mockServer; + + String validCsarFileLocation = "src/test/resources/"; + + private final String validRappFile = "valid-rapp-package.csar"; + + @BeforeEach + public void init() { + mockServer = MockRestServiceServer.createServer(restTemplate); + } + + @ParameterizedTest + @EnumSource(value = HttpStatus.class, names = {"CREATED", "CONFLICT"}) + void testChartUpload(HttpStatus status) { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + deploymentItems.forEach(deploymentItem -> mockServer.expect(ExpectedCount.once(), + requestTo(deploymentItem.getTargetServerUri())).andExpect(method(HttpMethod.POST)) + .andRespond(withStatus(status))); + assertTrue(deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + mockServer.verify(); + } + + @Test + void testChartUploadNoArtifacts() { + String invalidRappFile = "invalid-rapp-package.csar"; + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(invalidRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + assertTrue(deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + } + + @Test + void testChartUploadFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + deploymentItems.stream().findFirst().ifPresent(deploymentItem -> mockServer.expect(ExpectedCount.once(), + requestTo(deploymentItem.getTargetServerUri())).andExpect(method(HttpMethod.POST)) + .andRespond(withServerError())); + RappHandlerException exception = assertThrows(RappHandlerException.class, + () -> deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + mockServer.verify(); + } + + @Test + void testChartUploadFailureWithNotFound() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + deploymentItems.stream().findFirst().ifPresent(deploymentItem -> mockServer.expect(ExpectedCount.once(), + requestTo(deploymentItem.getTargetServerUri())).andExpect(method(HttpMethod.POST)).andRespond( + withStatus(HttpStatus.NOT_FOUND))); + assertFalse(deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + mockServer.verify(); + } + + @Test + void testChartUploadFailureWithException() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + deploymentItems.stream().findFirst().ifPresent(deploymentItem -> mockServer.expect(ExpectedCount.once(), + requestTo(deploymentItem.getTargetServerUri())).andExpect(method(HttpMethod.POST)).andRespond( + withException(new IOException()))); + RappHandlerException exception = assertThrows(RappHandlerException.class, + () -> deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + mockServer.verify(); + } + + @Test + void testChartUploadFailureWithTooManyRequests() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + deploymentItems.stream().findFirst().ifPresent(deploymentItem -> mockServer.expect(ExpectedCount.once(), + requestTo(deploymentItem.getTargetServerUri())).andExpect(method(HttpMethod.POST)) + .andRespond(withTooManyRequests())); + assertFalse(deploymentArtifactsService.configureDeploymentArtifacts(rapp)); + mockServer.verify(); + } +} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java index 4154b6c..9dc4987 100755 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java +++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java @@ -60,6 +60,9 @@ class RappServiceTest { @MockBean DmeDeployer dmeDeployer; + @MockBean + DeploymentArtifactsService deploymentArtifactsService; + @MockBean SmeLifecycleManager smeLifecycleManager; @@ -80,6 +83,7 @@ class RappServiceTest { when(acmDeployer.primeRapp(any())).thenReturn(true); when(dmeDeployer.primeRapp(any())).thenReturn(true); when(smeDeployer.primeRapp(any())).thenReturn(true); + when(deploymentArtifactsService.configureDeploymentArtifacts(any())).thenReturn(true); assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode()); assertEquals(RappState.PRIMED, rapp.getState()); } @@ -100,6 +104,7 @@ class RappServiceTest { void testPrimeRappAcmFailure() { Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + when(deploymentArtifactsService.configureDeploymentArtifacts(any())).thenReturn(true); when(acmDeployer.primeRapp(any())).thenReturn(false); when(dmeDeployer.primeRapp(any())).thenReturn(true); RappHandlerException rappHandlerException = @@ -112,6 +117,7 @@ class RappServiceTest { void testPrimeRappDmeFailure() { Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + when(deploymentArtifactsService.configureDeploymentArtifacts(any())).thenReturn(true); when(acmDeployer.primeRapp(any())).thenReturn(true); when(dmeDeployer.primeRapp(any())).thenReturn(false); RappHandlerException rappHandlerException = @@ -120,6 +126,16 @@ class RappServiceTest { assertEquals(RappState.COMMISSIONED, rapp.getState()); } + @Test + void testPrimeRappDeployArtifactFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + when(deploymentArtifactsService.configureDeploymentArtifacts(any())).thenReturn(false); + RappHandlerException rappHandlerException = + assertThrows(RappHandlerException.class, () -> rappService.primeRapp(rapp)); + assertEquals(HttpStatus.BAD_GATEWAY, rappHandlerException.getStatusCode()); + assertEquals(RappState.COMMISSIONED, rapp.getState()); + } @Test void testDeprimeRapp() { diff --git a/rapp-manager-application/src/test/resources/invalid-rapp-package.csar b/rapp-manager-application/src/test/resources/invalid-rapp-package.csar index dc18b5b790c778cdbbeec5be81681b66454868be..97efcb5f5da02471f7c1d896ee60e353d023a53f 100755 GIT binary patch delta 1025 zcmV+c1pfPsHs>_3o)Z!P00;n?Voq2t?L0&=0{{Sl3zM)D8-G?!kJB&^y|1+Y!Q$R% zla>O#fdC01A*2Pa*3_PMtva@`okIBajGHt`)3jQ?BzkG;_vY)(Ox$RL04{N(jEc&d z!1w3_J*-#*1ywqYyoOTqoENt@w>J`l@XEyl>#g!3GU=^jcEdIv@#$7DFp^d1!H_w7 zdH*_@kt6G4SbyE#Fg9ZlB#*VjkR{g%kJedjw>6JQAtB;{X{^NVq%mgToK^x-0{7_m zO5p1@CF>L8@JY_wA~JG9fhgn=JSpMH+a~KLN7PX@=%Z@mwI*E%uH=g4#T*w;m(OPS z{Ka~f7jixW`aN3|%VoaEpDph0?xu~+9=rk*dpC7mUw?E1Ycb`fZ&RKP;so)4CG=o1 z1UHotsbW5?zH8awFqw2p?3F~nVsGw0wa2Fo;08+UyvzuhqzzM=_YC|Vxo~o*a~h6= zGTqU6$G+j(!4_ws>HaBmuY9aPbFIvdd;D4{k0qM8Vrb-NGGV8DgYld7J8DcszX5?{ z1X}$#X=m@=lNdv;BkP=I^83V)8Wo0B7QLh+?_z^;QWzAXEMu|3jSh0yPi9lVizhQBtl7}L8mXMI-?6dTkW6thBSH1qlDAq+ z<+M{qCcWO%_Yv!_c6BT}QNA>fmpt4f`d`xXEIVRK|IZDvqQ1qJ{B000F51psOR008G000000Ega6Y delta 1124 zcmV-q1e^QkG>kT|o)eJ<6qB+O8GlzxZ{s!)z6Z#EAbgh+$&QotEk$-wqYnhgcCQ3Y zj%>md$x@WJ+F#$HWZ8N-4Yp0OI!T=O%s0c4Hw9-@Kqj^H(&&O7z!mtiBEBXSGPeq7 z#d1XxnqFUBUkNCsTQLF=VfcJCt@6xVnvd44vV|xeFP65Hc^s_dBpHLTBOTm zvPkY1x3{;`!ur6RWZIwARDV@e=C%mIIS%B|?;Ie??iO!sI|v9GYPYztA* zRKL%8kj|G(Q6=@BI{34c4sy_bML>%`P=xgPHTbW_?XfT(T*f${5PwthTjO^}LEp<7 zW3EISIid?Qz*GT425DKoBF14^3hxlXV#IN>+5lFdG4A6M{S;1O)-DT}CL2SBkid`w zX{IPS7X#B!xA0S6If4&BxhP?h_P`WrLXjn z4-=ZzL*emx{nj?xFuvchQoTzX;rkEXMeo%tBfOnSi~poqK7Synmk)98!f2jl)CzkTF5IDho^s<;=2;RC2Hl5Rywx_n0+M-MhGV zy9M(#>_y9o7%vr!V1S)!m(;Tj(uNf7D(icg;znn9uX+q;sCOu=Gfb18^oV18CZ}yK zCVbjUEkeG2k$+=MGb_(w=hc_y^^%4cK%d1M^fZhU+S+m`wgEMcvpyb9-u5`1jNhtq zD~Ej_k!GD~h)F=z(BsR+9*U>0iZ5ckg<2}ZL4zZuHye*DRnNojQhSmKi)}2xDpQ5| zy2fp}E0aluGPB2){pRV!dh_$gUw^x4cQsIR1UqqYkkC<0%r6S^R~m68HP9GC1&JogS~EIA;Mf z>umN0q51a+Ext!+`HE2c&lLS{#XniZUxheXykq%Ci^#D2=?_-^zX4E72MB9?Es*L1 z000~h0097y8nYD_rUD}r02BZS2nYZ}O2Srad@Ydb0{{RV4*&oZ0000000000005KT q85@%w8Y&>f7XScZb7U@UW>8B71^@s600jUA07d}-0I(SV0000;cnyF6 diff --git a/rapp-manager-application/src/test/resources/valid-rapp-package.csar b/rapp-manager-application/src/test/resources/valid-rapp-package.csar index ffe2f4bdef191af5ab8b7babf74ce3c52e7f5242..667317e84c68818fd455a06ea937845d297d03f9 100755 GIT binary patch delta 1045 zcmX@IgYoAM#toKoLcu*g5#c`EMLQT77}Qu97(^H*Z}b+czZ>M+ecM1_FZ(C?p7;Om zn4J8zZ3DONmgR3_&zySfqTuZ`iTU07_b22xUQVfgz0^#i^4Zzy#paK>W%$Lv#T4b_-5otqZistV6F51iuiAnRFm zv)AhX$Z%+N) zcSE#2cHZ;;?yIb87@msH+V|dmX(Ru?jFdKYzI}cByZ?=!(L%YGUzf*UHmcbru>E^Na`i{a z)YCs^9!mau$?k@5)w7KF=7k>{GOgQVf7_d@yk5hx<=$+q(_J>YpOkp-*OuDI&D-qY z{GCa8*<<;XCK<`^Ii1NLD@`_t;G10LE5(=(6e(u%)0`aOFE&}m&x>gRgjweo%T%Nd z7R}c-oP0h&V6ut76l2|FfBzz;Gy|Z7_~cvuv5e~`TLgqNew#cYAd@M;c=E&mxyh1& zIZWXuU}lVo<7E9X8GZ={1qK-S?-)B-FesIAGmw;?yv5WUZ1~L}DdsO`43qDe`Ga%_ zpz1KOm|Pf~!qf$#q$YP;*nsuehDb5>TY`lqSXzU$O+FRE$27@m@`X^j$v;B8nBG8` zl7ae@6|9B9nz93>7(Y)wAKJzI(}rR4LmP152nwS((9xD*vZk#WIFNpXNik0X@~doJ z!TPhprI=6If%x*1mxTu~GdnO$E_4)~0 delta 1001 zcmeylgYn1?#toKo^|Fj%lKFo-ZPFu0_qW#(m;Waj4;>n9ec=v5}> z=4=h|?r$;>*f;x!JV$v*L|FOGnHihZcB_BCcg4tK@+Gre)x`S0d?$<_1@4$K^Sxm| z+j5=7Dy==rItl5DpLXS%Cb=%Qx!$OHt*w^JT!$4# z=hRNOK4+ENs#!RdZMRd=_Vh3iBM8x~!0Y@VXkYFDIQ9g=-ea;@&U1g~=sF3i#j zR-Uz7EdO-OLJp~gsnh3(yp$H<+2FO`JA1K-#PR6E(=JyF%u|b#*z5Rb-(A)ZA1gTz zY1DFS)Ug+Cx!YE_quYG;S)0iEX;%ug?kWU_UJaJ4N-Q=ytaj+?iQ}7OxU5tb7aHyM z4BPG_S8mdE)9!N`5}|@yyPeA_{cFmk)Q12lf@jZ#4vfSlIEmfw#g2@B9j}!_?YJd zg+40jLWGo^}K{kIZD*2tH;>O@_(++M<&iG?hR~ z8vUf0v%x}QlehTAFxpNQ^elKd_rg$pkE}Yoj-Lzlku|X7eCEW(`w@$%5vRlP8;k)lUqP zVy=S4W-@QLVwfyoBRjdvSbuV~jWAH97V|!9kXRhhU@gWYll#NMnR#p(Cdb*D zfsED-mtu|ua@X6sf{mRI artifactFileList = - jsonNode.at("/topology_template/node_templates/applicationServiceDescriptor/artifacts") - .findValuesAsText("file"); + JsonNode jsonNode = getAsdContentNode(asdContent); + List artifactFileList = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file"); return artifactFileList.stream() .allMatch(artifactFile -> isFileExistsInCsar(multipartFile, artifactFile)); } catch (RappHandlerException e) { @@ -180,21 +190,51 @@ public class RappCsarConfigurationHandler { throw new RappHandlerException(HttpStatus.BAD_REQUEST, "ASD definition in rApp package is invalid."); } + JsonNode getAsdContentNode(String asdContent) throws JsonProcessingException { + return objectMapper.readTree(new Gson().toJsonTree(new Yaml().load(asdContent)).toString()); + } + + String getAsdDefinitionLocation(final File csarFile) { + return getAsdDefinitionLocation(getFileFromCsar(csarFile, TOSCA_METADATA_LOCATION).toString()); + } + String getAsdDefinitionLocation(final MultipartFile multipartFile) { + return getAsdDefinitionLocation(getFileFromCsar(multipartFile, TOSCA_METADATA_LOCATION).toString()); + } + + String getAsdDefinitionLocation(final String toscaMetadata) { String asdLocation = ""; - final ByteArrayOutputStream fileContent = getFileFromCsar(multipartFile, TOSCA_METADATA_LOCATION); - if (fileContent != null) { - final String toscaMetadata = fileContent.toString(); - if (!toscaMetadata.isEmpty()) { - final String entry = - filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_INDEX)).iterator() - .next(); - asdLocation = entry.replace(ENTRY_DEFINITIONS_INDEX + ":", "").trim(); - } + if (toscaMetadata != null && !toscaMetadata.isEmpty()) { + final String entry = + filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_INDEX)).iterator() + .next(); + asdLocation = entry.replace(ENTRY_DEFINITIONS_INDEX + ":", "").trim(); } return asdLocation; } + public List getDeploymentItems(Rapp rApp) { + List deploymentItems = new ArrayList<>(); + File csarFile = getCsarFile(rApp); + String asdDefinitionLocation = getAsdDefinitionLocation(csarFile); + if (asdDefinitionLocation != null && !asdDefinitionLocation.isEmpty()) { + try { + String asdContent = getFileFromCsar(csarFile, asdDefinitionLocation).toString(); + JsonNode jsonNode = getAsdContentNode(asdContent); + JsonNode artifactsJsonNode = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER); + artifactsJsonNode.forEach(artifactJsonNode -> { + DeploymentItem deploymentItem = + objectMapper.convertValue(artifactJsonNode.at("/properties"), DeploymentItem.class); + deploymentItem.setFile(artifactJsonNode.at("/file").asText()); + deploymentItems.add(deploymentItem); + }); + } catch (Exception e) { + logger.warn("Unable to get the deployment items", e); + } + } + return deploymentItems; + } + public String getSmeProviderDomainPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { return getPayload(rapp, getResourceUri(SME_PROVIDER_FUNCS_LOCATION, rappSMEInstance.getProviderFunction())); diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java index 81468ee..e769b12 100755 --- a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java @@ -27,10 +27,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonSyntaxException; import com.oransc.rappmanager.models.exception.RappHandlerException; import com.oransc.rappmanager.models.rapp.Rapp; import com.oransc.rappmanager.models.rapp.RappResources; @@ -41,6 +44,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Stream; @@ -51,6 +55,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpStatus; @@ -67,11 +72,14 @@ class RappCsarConfigurationHandlerTest { String validCsarFileLocation = "src/test/resources/"; - private final String validRappFile = "valid-rapp-package.csar"; private final String invalidRappFile = "invalid-rapp-package.csar"; + private final String invalidRappNoAsdFile = "invalid-rapp-package-no-asd-yaml.csar"; + + private final String invalidRappEmptyAsdFile = "invalid-rapp-package-empty-asd-yaml.csar"; + @Test void testCsarPackageValidationSuccess() throws IOException { String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; @@ -84,7 +92,6 @@ class RappCsarConfigurationHandlerTest { @ParameterizedTest @MethodSource("getInvalidCsarPackage") void testCsarPackageValidationFailure(MultipartFile multipartFile) { - System.out.println(multipartFile.getOriginalFilename()); RappHandlerException exception = assertThrows(RappHandlerException.class, () -> rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); @@ -361,4 +368,32 @@ class RappCsarConfigurationHandlerTest { assertNotNull(dmeInfoConsumerPayload); } + @Test + void testListDeploymentItems() { + Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build(); + List deploymentItems = rappCsarConfigurationHandler.getDeploymentItems(rapp); + assertEquals(2, deploymentItems.size()); + } + + @ParameterizedTest + @ValueSource(strings = {invalidRappNoAsdFile, invalidRappEmptyAsdFile}) + void testListDeploymentItemsNoAsd(String packageName) { + Rapp rapp = Rapp.builder().name("").packageName(packageName).packageLocation(validCsarFileLocation).build(); + assertThat(rappCsarConfigurationHandler.getDeploymentItems(rapp)).isEmpty(); + } + + @Test + void testListDeploymentItemsWithException() throws JsonProcessingException { + Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build(); + doThrow(new JsonSyntaxException("")).when(rappCsarConfigurationHandler).getAsdContentNode(any()); + assertThat(rappCsarConfigurationHandler.getDeploymentItems(rapp)).isEmpty(); + } + + @Test + void testGetArtifactPayload() { + Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build(); + assertNotNull(rappCsarConfigurationHandler.getArtifactPayload(rapp, + "Artifacts/Deployment/HELM/ransliceassurance-1.0.0.tgz")); + + } } diff --git a/rapp-manager-models/src/test/resources/invalid-rapp-package-empty-asd-yaml.csar b/rapp-manager-models/src/test/resources/invalid-rapp-package-empty-asd-yaml.csar new file mode 100755 index 0000000000000000000000000000000000000000..e614a19309447c1269c81d4de58d464a5dc3c6eb GIT binary patch literal 23233 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 G@BR<@euhN= literal 0 HcmV?d00001 diff --git a/rapp-manager-models/src/test/resources/valid-rapp-package.csar b/rapp-manager-models/src/test/resources/valid-rapp-package.csar index ffe2f4bdef191af5ab8b7babf74ce3c52e7f5242..667317e84c68818fd455a06ea937845d297d03f9 100755 GIT binary patch delta 1045 zcmX@IgYoAM#toKoLcu*g5#c`EMLQT77}Qu97(^H*Z}b+czZ>M+ecM1_FZ(C?p7;Om zn4J8zZ3DONmgR3_&zySfqTuZ`iTU07_b22xUQVfgz0^#i^4Zzy#paK>W%$Lv#T4b_-5otqZistV6F51iuiAnRFm zv)AhX$Z%+N) zcSE#2cHZ;;?yIb87@msH+V|dmX(Ru?jFdKYzI}cByZ?=!(L%YGUzf*UHmcbru>E^Na`i{a z)YCs^9!mau$?k@5)w7KF=7k>{GOgQVf7_d@yk5hx<=$+q(_J>YpOkp-*OuDI&D-qY z{GCa8*<<;XCK<`^Ii1NLD@`_t;G10LE5(=(6e(u%)0`aOFE&}m&x>gRgjweo%T%Nd z7R}c-oP0h&V6ut76l2|FfBzz;Gy|Z7_~cvuv5e~`TLgqNew#cYAd@M;c=E&mxyh1& zIZWXuU}lVo<7E9X8GZ={1qK-S?-)B-FesIAGmw;?yv5WUZ1~L}DdsO`43qDe`Ga%_ zpz1KOm|Pf~!qf$#q$YP;*nsuehDb5>TY`lqSXzU$O+FRE$27@m@`X^j$v;B8nBG8` zl7ae@6|9B9nz93>7(Y)wAKJzI(}rR4LmP152nwS((9xD*vZk#WIFNpXNik0X@~doJ z!TPhprI=6If%x*1mxTu~GdnO$E_4)~0 delta 1001 zcmeylgYn1?#toKo^|Fj%lKFo-ZPFu0_qW#(m;Waj4;>n9ec=v5}> z=4=h|?r$;>*f;x!JV$v*L|FOGnHihZcB_BCcg4tK@+Gre)x`S0d?$<_1@4$K^Sxm| z+j5=7Dy==rItl5DpLXS%Cb=%Qx!$OHt*w^JT!$4# z=hRNOK4+ENs#!RdZMRd=_Vh3iBM8x~!0Y@VXkYFDIQ9g=-ea;@&U1g~=sF3i#j zR-Uz7EdO-OLJp~gsnh3(yp$H<+2FO`JA1K-#PR6E(=JyF%u|b#*z5Rb-(A)ZA1gTz zY1DFS)Ug+Cx!YE_quYG;S)0iEX;%ug?kWU_UJaJ4N-Q=ytaj+?iQ}7OxU5tb7aHyM z4BPG_S8mdE)9!N`5}|@yyPeA_{cFmk)Q12lf@jZ#4vfSlIEmfw#g2@B9j}!_?YJd zg+40jLWGo^}K{kIZD*2tH;>O@_(++M<&iG?hR~ z8vUf0v%x}QlehTAFxpNQ^elKd_rg$pkE}Yoj-Lzlku|X7eCEW(`w@$%5vRlP8;k)lUqP zVy=S4W-@QLVwfyoBRjdvSbuV~jWAH97V|!9kXRhhU@gWYll#NMnR#p(Cdb*D zfsED-mtu|ua@X6sf{mRI - Specify artifact type. - required: true - type: string - constraints: - - valid_values: ["helm_chart"] + version: 0.1 + derived_from: tosca.artifacts.Root + description: "Describes the artifact type of asd deployment item" + file: "Relative path of the artifact in the package" + properties: + item_id: + description: "The identifier of this asd deployment item" + required: true + type: string + artifact_type: + description: > + Specify artifact type. + required: true + type: string + constraints: + - valid_values: ["helm_chart"] + target_server: + description: > + Specify target server for artifact. + required: true + type: string + constraints: + - valid_values: [ "chartmuseum" ] + target_server_uri: + description: "URI of the target server" + required: true + type: string \ No newline at end of file -- 2.16.6