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 <aravindhan.a@est.tech>
--- /dev/null
+/*
+ * ============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<DeploymentItem> 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<ByteArrayResource> requestHttpEntity =
+ new HttpEntity<>(rappCsarConfigurationHandler.getArtifactPayload(rApp, deploymentItem.getFile()),
+ httpHeaders);
+ ResponseEntity<String> 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;
+ }
+}
private final List<RappDeployer> 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<String> 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();
}
--- /dev/null
+/*
+ * ============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<DeploymentItem> 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<DeploymentItem> 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<DeploymentItem> 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<DeploymentItem> 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<DeploymentItem> 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();
+ }
+}
@MockBean
DmeDeployer dmeDeployer;
+ @MockBean
+ DeploymentArtifactsService deploymentArtifactsService;
+
@MockBean
SmeLifecycleManager smeLifecycleManager;
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());
}
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 =
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 =
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() {
--- /dev/null
+/*
+ * ============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.models.csar;
+
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder(toBuilder = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+public class DeploymentItem {
+
+ String file;
+ DeploymentItemArtifactType artifactType;
+ String itemId;
+ DeploymentItemTargetServer targetServer;
+ String targetServerUri;
+}
--- /dev/null
+/*
+ * ============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.models.csar;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum DeploymentItemArtifactType {
+ @JsonProperty("helm_chart") HELMCHART;
+}
--- /dev/null
+/*
+ * ============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.models.csar;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum DeploymentItemTargetServer {
+
+ @JsonProperty("chartmuseum") CHARTMUSEUM;
+}
import static com.google.common.base.Splitter.on;
import static com.google.common.collect.Iterables.filter;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
private static final String DME_CONSUMER_INFO_TYPES_LOCATION = "Files/Dme/consumerinfotypes";
private static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers";
private static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers";
+ private static final String ARTIFACTS_LOCATION_JSON_POINTER =
+ "/topology_template/node_templates/applicationServiceDescriptor/artifacts";
public boolean isValidRappPackage(MultipartFile multipartFile) {
"COMPOSITIONID", String.valueOf(compositionId));
}
+ public ByteArrayResource getArtifactPayload(Rapp rapp, String location) {
+ return new ByteArrayResource(getByteArrayStreamPayload(rapp, location).toByteArray());
+ }
+
String getPayload(Rapp rapp, String location) {
+ return getByteArrayStreamPayload(rapp, location).toString();
+ }
+
+ ByteArrayOutputStream getByteArrayStreamPayload(Rapp rapp, String location) {
logger.debug("Getting payload for {} from {}", rapp.getRappId(), location);
File csarFile = getCsarFile(rapp);
- return getFileFromCsar(csarFile, location).toString();
+ return getFileFromCsar(csarFile, location);
}
File getCsarFile(Rapp rapp) {
if (asdLocation != null && !asdLocation.isEmpty() && isFileExistsInCsar(multipartFile, asdLocation)) {
try {
String asdContent = getFileFromCsar(multipartFile, asdLocation).toString();
- String asdJsonContent = new Gson().toJsonTree(new Yaml().load(asdContent)).toString();
- JsonNode jsonNode = objectMapper.readTree(asdJsonContent);
- List<String> artifactFileList =
- jsonNode.at("/topology_template/node_templates/applicationServiceDescriptor/artifacts")
- .findValuesAsText("file");
+ JsonNode jsonNode = getAsdContentNode(asdContent);
+ List<String> artifactFileList = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file");
return artifactFileList.stream()
.allMatch(artifactFile -> isFileExistsInCsar(multipartFile, artifactFile));
} catch (RappHandlerException e) {
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<DeploymentItem> getDeploymentItems(Rapp rApp) {
+ List<DeploymentItem> 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()));
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;
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;
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;
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;
@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());
assertNotNull(dmeInfoConsumerPayload);
}
+ @Test
+ void testListDeploymentItems() {
+ Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build();
+ List<DeploymentItem> 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"));
+
+ }
}
\r
topology_template:\r
node_templates:\r
- applicationServiceDescriptor:\r
+ applicationServiceDescriptor:\r
type: tosca.nodes.asd\r
description: "rapp-all"\r
properties:\r
file: "Artifacts/Deployment/HELM/ransliceassurance-1.0.0.tgz"\r
properties:\r
artifact_type: "helm_chart"\r
- itemId: 1\r
+ target_server: "chartmuseum"\r
+ target_server_uri: "http://10.101.0.106:8879/charts/api/charts"\r
+ item_id: 1\r
oru-app:\r
type: tosca.artifacts.asd.deploymentItem\r
file: "Artifacts/Deployment/HELM/orufhrecovery-1.0.0.tgz"\r
properties:\r
artifact_type: "helm_chart"\r
- itemId: 2\r
+ target_server: "chartmuseum"\r
+ target_server_uri: "http://10.101.0.106:8879/charts/api/charts"\r
+ item_id: 2
\ No newline at end of file
artifact_types:
tosca.artifacts.asd.deploymentItem:
- 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"]
+ 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