From a9347ca2183dca1f722efd89eb76808e38f5a645 Mon Sep 17 00:00:00 2001 From: Grzegorz Wielgosinski Date: Wed, 2 Feb 2022 09:56:32 +0100 Subject: Add api for CNFO upgrade Issue-ID: SO-3845 Signed-off-by: Grzegorz Wielgosinski Change-Id: I8038742f15b1cc848c5f95186946c66bf0311479 --- .../so/adapters/cnf/client/MulticloudClient.java | 49 ++++++- .../cnf/model/MulticloudInstanceRequest.java | 12 ++ .../cnf/model/upgrade/InstanceUpgradeRequest.java | 158 +++++++++++++++++++++ .../onap/so/adapters/cnf/rest/CnfAdapterRest.java | 15 ++ .../service/upgrade/InstanceUpgradeService.java | 60 ++++++++ .../upgrade/InstanceUpgradeServiceTest.java | 111 +++++++++++++++ 6 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/upgrade/InstanceUpgradeRequest.java create mode 100644 so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeService.java create mode 100644 so-cnf-adapter-application/src/test/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeServiceTest.java diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java index 762f192..605806b 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/client/MulticloudClient.java @@ -1,8 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * Modifications Copyright (C) 2021 Orange. + * ================================================================================ + * 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 org.onap.so.adapters.cnf.client; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.so.adapters.cnf.MulticloudConfiguration; +import org.onap.so.adapters.cnf.model.MulticloudInstanceRequest; import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheck; import org.onap.so.adapters.cnf.model.healthcheck.K8sRbInstanceHealthCheckSimple; import org.onap.so.adapters.cnf.model.statuscheck.K8sRbInstanceStatus; @@ -39,6 +61,18 @@ public class MulticloudClient { this.objectMapper = new ObjectMapper(); } + public String upgradeInstance(String instanceId, MulticloudInstanceRequest upgradeRequest) throws BadResponseException { + MulticloudApiUrl multicloudApiUrl = new MulticloudApiUrl(multicloudConfiguration); + multicloudApiUrl.setInstanceId(instanceId); + String endpoint = multicloudApiUrl.apiUrl() + "/upgrade"; + ResponseEntity result = restTemplate.exchange(endpoint, POST, getHttpEntity(upgradeRequest), String.class); + checkResponseStatusCode(result); + log.info("upgradeInstance response status: {}", result.getStatusCode()); + String body = result.getBody(); + log.debug("upgradeInstance response body: {}", body); + return body; + } + public K8sRbInstanceStatus getInstanceStatus(String instanceId) throws BadResponseException { MulticloudApiUrl multicloudApiUrl = new MulticloudApiUrl(multicloudConfiguration); multicloudApiUrl.setInstanceId(instanceId); @@ -105,14 +139,25 @@ public class MulticloudClient { } } - private HttpEntity getHttpEntity() { + private HttpEntity getHttpEntity() { + HttpHeaders headers = getHttpHeaders(); + + return new HttpEntity<>(headers); + } + + private HttpHeaders getHttpHeaders() { HttpHeaders headers = new HttpHeaders(); List acceptableMediaTypes = new ArrayList<>(); acceptableMediaTypes.add(MediaType.APPLICATION_JSON); headers.setAccept(acceptableMediaTypes); headers.setContentType(MediaType.APPLICATION_JSON); + return headers; + } - return new HttpEntity<>(headers); + private HttpEntity getHttpEntity(T body) { + HttpHeaders headers = getHttpHeaders(); + + return new HttpEntity<>(body, headers); } private void checkResponseStatusCode(ResponseEntity result) throws BadResponseException { diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/MulticloudInstanceRequest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/MulticloudInstanceRequest.java index 20af63e..fa58cfd 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/MulticloudInstanceRequest.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/MulticloudInstanceRequest.java @@ -84,4 +84,16 @@ public class MulticloudInstanceRequest { this.releaseName = releaseName; } + @Override + public String toString() { + return "MulticloudInstanceRequest{" + + "cloudRegion='" + cloudRegion + '\'' + + ", rbName='" + rbName + '\'' + + ", rbVersion='" + rbVersion + '\'' + + ", profileName='" + profileName + '\'' + + ", labels=" + labels + + ", overrideValues=" + overrideValues + + ", releaseName='" + releaseName + '\'' + + '}'; + } } diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/upgrade/InstanceUpgradeRequest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/upgrade/InstanceUpgradeRequest.java new file mode 100644 index 0000000..a4a9ebf --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/model/upgrade/InstanceUpgradeRequest.java @@ -0,0 +1,158 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * Modifications Copyright (C) 2021 Orange. + * ================================================================================ + * 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 org.onap.so.adapters.cnf.model.upgrade; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(value = "true") +public class InstanceUpgradeRequest { + + @JsonProperty("modelInvariantId") + private String modelInvariantId; + + @JsonProperty("modelCustomizationId") + private String modelCustomizationId; + + @JsonProperty("k8sRBProfileName") + private String k8sRBProfileName; + + @JsonProperty("k8sRBInstanceStatusCheck") + private boolean k8sRBInstanceStatusCheck; + + @JsonProperty("cloudRegionId") + private String cloudRegionId; + + @JsonProperty("vfModuleUUID") + private String vfModuleUUID; + + @JsonProperty("labels") + private Map labels; + + @JsonProperty("override-values") + private Map overrideValues; + + + public String getModelInvariantId() { + return modelInvariantId; + } + + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + public String getModelCustomizationId() { + return modelCustomizationId; + } + + public void setModelCustomizationId(String modelCustomizationId) { + this.modelCustomizationId = modelCustomizationId; + } + + public String getK8sRBProfileName() { + return k8sRBProfileName; + } + + public void setK8sRBProfileName(String k8sRBProfileName) { + this.k8sRBProfileName = k8sRBProfileName; + } + + public boolean isK8sRBInstanceStatusCheck() { + return k8sRBInstanceStatusCheck; + } + + public void setK8sRBInstanceStatusCheck(boolean k8sRBInstanceStatusCheck) { + this.k8sRBInstanceStatusCheck = k8sRBInstanceStatusCheck; + } + + public String getCloudRegionId() { + return cloudRegionId; + } + + public void setCloudRegionId(String cloudRegionId) { + this.cloudRegionId = cloudRegionId; + } + + public String getVfModuleUUID() { + return vfModuleUUID; + } + + public void setVfModuleUUID(String vfModuleUUID) { + this.vfModuleUUID = vfModuleUUID; + } + + public Map getLabels() { + return labels; + } + + public void setLabels(Map labels) { + this.labels = labels; + } + + public Map getOverrideValues() { + return overrideValues; + } + + public void setOverrideValues(Map overrideValues) { + this.overrideValues = overrideValues; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InstanceUpgradeRequest that = (InstanceUpgradeRequest) o; + return k8sRBInstanceStatusCheck == that.k8sRBInstanceStatusCheck && + Objects.equals(modelInvariantId, that.modelInvariantId) && + Objects.equals(modelCustomizationId, that.modelCustomizationId) && + Objects.equals(k8sRBProfileName, that.k8sRBProfileName) && + Objects.equals(cloudRegionId, that.cloudRegionId) && + Objects.equals(vfModuleUUID, that.vfModuleUUID) && + Objects.equals(labels, that.labels) && + Objects.equals(overrideValues, that.overrideValues); + } + + @Override + public int hashCode() { + return Objects.hash(modelInvariantId, modelCustomizationId, k8sRBProfileName, k8sRBInstanceStatusCheck, cloudRegionId, vfModuleUUID, labels, overrideValues); + } + + @Override + public String toString() { + return "InstanceUpgradeRequest{" + + "modelInvariantId='" + modelInvariantId + '\'' + + ", modelCustomizationId='" + modelCustomizationId + '\'' + + ", k8sRBProfileName='" + k8sRBProfileName + '\'' + + ", k8sRBInstanceStatusCheck=" + k8sRBInstanceStatusCheck + + ", cloudRegionId='" + cloudRegionId + '\'' + + ", vfModuleUUID='" + vfModuleUUID + '\'' + + ", labels=" + labels + + ", overrideValues=" + overrideValues + + '}'; + } + +} diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java index ee8a362..bc85dc4 100644 --- a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/CnfAdapterRest.java @@ -54,10 +54,12 @@ import org.onap.so.adapters.cnf.model.aai.AaiCallbackResponse; import org.onap.so.adapters.cnf.model.healthcheck.HealthCheckResponse; import org.onap.so.adapters.cnf.model.instantiation.AaiRequest; import org.onap.so.adapters.cnf.model.statuscheck.StatusCheckResponse; +import org.onap.so.adapters.cnf.model.upgrade.InstanceUpgradeRequest; import org.onap.so.adapters.cnf.service.CnfAdapterService; import org.onap.so.adapters.cnf.service.aai.AaiService; import org.onap.so.adapters.cnf.service.healthcheck.HealthCheckService; import org.onap.so.adapters.cnf.service.statuscheck.SimpleStatusCheckService; +import org.onap.so.adapters.cnf.service.upgrade.InstanceUpgradeService; import org.onap.so.client.exception.BadResponseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,6 +85,7 @@ public class CnfAdapterRest { private final CloseableHttpClient httpClient = HttpClients.createDefault(); private final SimpleStatusCheckService simpleStatusCheckService; private final HealthCheckService healthCheckService; + private final InstanceUpgradeService instanceUpgradeService; private final CnfAdapterService cnfAdapterService; private final SoCallbackClient callbackClient; private final AaiService aaiService; @@ -91,18 +94,30 @@ public class CnfAdapterRest { @Autowired public CnfAdapterRest(SimpleStatusCheckService simpleStatusCheckService, HealthCheckService healthCheckService, + InstanceUpgradeService instanceUpgradeService, CnfAdapterService cnfAdapterService, SoCallbackClient callbackClient, AaiService aaiService, MulticloudConfiguration multicloudConfiguration) { this.simpleStatusCheckService = simpleStatusCheckService; this.healthCheckService = healthCheckService; + this.instanceUpgradeService = instanceUpgradeService; this.cnfAdapterService = cnfAdapterService; this.aaiService = aaiService; this.callbackClient = callbackClient; this.uri = multicloudConfiguration.getMulticloudUrl(); } + @ResponseBody + @RequestMapping(value = {"/api/cnf-adapter/v1/instance/{instanceID}/upgrade"}, method = RequestMethod.POST, + produces = "application/json", consumes = "application/json") + public String upgrade(@PathVariable("instanceID") String instanceId, + @RequestBody InstanceUpgradeRequest upgradeRequest) throws BadResponseException { + logger.info("upgrade called for instance {}.", instanceId); + return instanceUpgradeService.upgradeInstance(instanceId, upgradeRequest); + } + + @ResponseBody @RequestMapping(value = {"/api/cnf-adapter/v1/healthcheck"}, method = RequestMethod.POST, produces = "application/json") diff --git a/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeService.java b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeService.java new file mode 100644 index 0000000..2fd26fb --- /dev/null +++ b/so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeService.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * Modifications Copyright (C) 2021 Orange. + * ================================================================================ + * 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 org.onap.so.adapters.cnf.service.upgrade; + +import org.onap.so.adapters.cnf.client.MulticloudClient; +import org.onap.so.adapters.cnf.model.MulticloudInstanceRequest; +import org.onap.so.adapters.cnf.model.upgrade.InstanceUpgradeRequest; +import org.onap.so.client.exception.BadResponseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class InstanceUpgradeService { + + private static final Logger logger = LoggerFactory.getLogger(InstanceUpgradeService.class); + + private final MulticloudClient instanceApi; + + public InstanceUpgradeService(MulticloudClient multicloudClient) { + this.instanceApi = multicloudClient; + } + + public String upgradeInstance(String instanceId, InstanceUpgradeRequest upgradeRequest) throws BadResponseException { + logger.debug("UpgradeService upgradeInstance for instanceId: {}- START", instanceId); + MulticloudInstanceRequest multicloudInstanceRequest = new MulticloudInstanceRequest(); + if (upgradeRequest.getK8sRBProfileName() != null) { + multicloudInstanceRequest.setRbName(upgradeRequest.getModelInvariantId()); + multicloudInstanceRequest.setRbVersion(upgradeRequest.getModelCustomizationId()); + multicloudInstanceRequest.setProfileName(upgradeRequest.getK8sRBProfileName()); + multicloudInstanceRequest.setCloudRegion(upgradeRequest.getCloudRegionId()); + multicloudInstanceRequest.setLabels(upgradeRequest.getLabels()); + multicloudInstanceRequest.setOverrideValues(upgradeRequest.getOverrideValues()); + } else { + throw new NullPointerException("k8sProfileName should not be null"); + } + logger.info("Upgrade request: {}", multicloudInstanceRequest); + logger.debug("UpgradeService upgradeInstance- END"); + return instanceApi.upgradeInstance(instanceId, multicloudInstanceRequest); + } +} diff --git a/so-cnf-adapter-application/src/test/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeServiceTest.java b/so-cnf-adapter-application/src/test/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeServiceTest.java new file mode 100644 index 0000000..74d258d --- /dev/null +++ b/so-cnf-adapter-application/src/test/java/org/onap/so/adapters/cnf/service/upgrade/InstanceUpgradeServiceTest.java @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + * Modifications Copyright (C) 2021 Samsung Technologies Co. + * Modifications Copyright (C) 2021 Orange. + * ================================================================================ + * 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 org.onap.so.adapters.cnf.service.upgrade; + + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.so.adapters.cnf.client.MulticloudClient; +import org.onap.so.adapters.cnf.model.MulticloudInstanceRequest; +import org.onap.so.adapters.cnf.model.upgrade.InstanceUpgradeRequest; +import org.onap.so.client.exception.BadResponseException; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@SpringBootTest +@RunWith(MockitoJUnitRunner.class) +public class InstanceUpgradeServiceTest { + + @InjectMocks + private InstanceUpgradeService tested; + + @Mock + MulticloudClient instanceApi; + + @Captor + ArgumentCaptor multicloudInstanceRequestCaptor; + + + @Test + public void shouldUpgradeInstanceSuccessfully() throws BadResponseException { + // given + String instanceId = "instanceId"; + InstanceUpgradeRequest upgradeRequest = mock(InstanceUpgradeRequest.class); + String k8sRBProfileName = "k8sRBProfileName"; + String modelInvariantId = "modelInvariantId"; + String modelCustomizationId = "modelCustomizationId"; + String cloudRegionId = "cloudRegionId"; + Map labels = mock(Map.class); + Map overrideValues = mock(Map.class); + String response = "response"; + + // when + when(upgradeRequest.getK8sRBProfileName()).thenReturn(k8sRBProfileName); + when(upgradeRequest.getModelInvariantId()).thenReturn(modelInvariantId); + when(upgradeRequest.getModelCustomizationId()).thenReturn(modelCustomizationId); + when(upgradeRequest.getCloudRegionId()).thenReturn(cloudRegionId); + when(upgradeRequest.getLabels()).thenReturn(labels); + when(upgradeRequest.getOverrideValues()).thenReturn(overrideValues); + when(instanceApi.upgradeInstance(eq(instanceId), any(MulticloudInstanceRequest.class))).thenReturn(response); + + // than + String actual = tested.upgradeInstance(instanceId, upgradeRequest); + + assertEquals(actual, response); + verify(instanceApi).upgradeInstance(eq(instanceId), multicloudInstanceRequestCaptor.capture()); + MulticloudInstanceRequest requestCaptureValue = multicloudInstanceRequestCaptor.getValue(); + assertEquals(requestCaptureValue.getRbName(), modelInvariantId); + assertEquals(requestCaptureValue.getRbVersion(), modelCustomizationId); + assertEquals(requestCaptureValue.getProfileName(), k8sRBProfileName); + assertEquals(requestCaptureValue.getLabels(), labels); + assertEquals(requestCaptureValue.getOverrideValues(), overrideValues); + } + + @Test(expected = RuntimeException.class) + public void shouldThrowRuntimeExceptionWhenProfileNameIsNull() throws BadResponseException { + // given + String instanceId = "instanceId"; + InstanceUpgradeRequest upgradeRequest = mock(InstanceUpgradeRequest.class); + + // when + when(upgradeRequest.getK8sRBProfileName()).thenReturn(null); + + // than + + tested.upgradeInstance(instanceId, upgradeRequest); + } + +} \ No newline at end of file -- cgit 1.2.3-korg